summaryrefslogtreecommitdiffstats
path: root/bindings/php5
diff options
context:
space:
mode:
authorBenjamin Dauvergne <bdauvergne@entrouvert.com>2010-01-04 09:13:36 +0000
committerBenjamin Dauvergne <bdauvergne@entrouvert.com>2010-01-04 09:13:36 +0000
commit5224c7cf675d6c8b2df9b3f4b43f8cd8d4eb8184 (patch)
treefc571c8d011bd0b73d932601e0b026f338e5d675 /bindings/php5
parent42062ff986a344f3f33a4465e106fede10aeaa6a (diff)
downloadlasso-5224c7cf675d6c8b2df9b3f4b43f8cd8d4eb8184.tar.gz
lasso-5224c7cf675d6c8b2df9b3f4b43f8cd8d4eb8184.tar.xz
lasso-5224c7cf675d6c8b2df9b3f4b43f8cd8d4eb8184.zip
Bindings: make the binding infrastructure understand GObject-introspections annotations
* bindings/bindings.py * bindings/utils.py: add convenience function to treat arguments tuple: (type,name,{annotations}). introduce new argument options, fix that arguments are 3-tuple of the form (type,name,annotations), where annotations is a dictionary. Key of this dictionnary can be: - optional, wheter the argument is necessary, it means it has a default value. - out, means that the pointer is a pointer of pointer, for bindings that can return exceptions, it will be returned instead of the integer error code, the only way to access error codes will be exceptions. - element-type, contained type of a list or an array, - key-type, value-type, type of respectively the key and value of a GHashTable. - transfer, wheter a the callee(for arguments)/caller(for return values) owns the values passed, it can be none,container(if the callee/caller only owns the container not the contained value) or full. doc.parameters is now a 3-tuple of (attribute-name, attribute-description, attribute-annotations) where attribute-annotations is a string of the form '(option1)(option2 option-arguments) etc.'. - add predicates for xml, list and time_t values. improve predicates for cstring and const modifier. * bindings/overrides.xml: 'out' arguments are not well supported for java, so skip functions using them. * bindings/java/lang.py bindings/php5/php_code.py bindings/php5/wrapper_source.py bindings/python/lang.py: - update language specifig binding generators for handling new annotations. - improve python method declaration, handle optional arguments with default values, factorize this chode in two methods, get_python_arg_decl and defval_to_python_value. * bindings/python/tests/Makefile.am bindings/python/tests/idwsf1_tests.py bindings/python/tests/idwsf2_tests.py: make test work with out of source build dir.
Diffstat (limited to 'bindings/php5')
-rw-r--r--bindings/php5/php_code.py21
-rw-r--r--bindings/php5/wrapper_source.py100
2 files changed, 106 insertions, 15 deletions
diff --git a/bindings/php5/php_code.py b/bindings/php5/php_code.py
index 76bae23d..64439778 100644
--- a/bindings/php5/php_code.py
+++ b/bindings/php5/php_code.py
@@ -22,7 +22,7 @@
import re
import sys
-import utils
+from utils import *
class PhpCode:
def __init__(self, binding_data, fd):
@@ -135,7 +135,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
print >> self.fd, ''
def generate_constructors(self, klass):
- method_prefix = utils.format_as_underscored(klass.name) + '_'
+ method_prefix = format_as_underscored(klass.name) + '_'
for m in self.binding_data.functions:
if m.name == method_prefix + 'new':
php_args = []
@@ -183,7 +183,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
for m in klass.members:
mtype = m[0]
- mname = utils.format_as_camelcase(m[1])
+ mname = format_as_camelcase(m[1])
options = m[2]
# Getters
@@ -253,7 +253,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
except IndexError:
setter = None
mname = re.match(r'lasso_.*_get_(\w+)', meth_name).group(1)
- mname =utils.format_as_camelcase(mname)
+ mname = format_as_camelcase(mname)
print >> self.fd, ' /**'
print >> self.fd, ' * @return %s' % self.get_docstring_return_type(m.return_type)
@@ -278,7 +278,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
print >> self.fd, ''
# second pass on methods, real methods
- method_prefix = utils.format_as_underscored(klass.name) + '_'
+ method_prefix = format_as_underscored(klass.name) + '_'
for m in methods:
if m.name.endswith('_new') or m.name.endswith('_new_from_dump') or \
m.name.endswith('_new_full'):
@@ -295,9 +295,13 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
mname = mname[len(method_prefix):]
php_args = []
c_args = []
+ outarg = None
for arg in m.args[1:]:
arg_type, arg_name, arg_options = arg
arg_name = '$' + arg_name
+ if is_out(arg):
+ assert not outarg
+ outarg = arg
if arg_options.get('optional'):
if arg_options.get('default'):
defval = arg_options.get('default')
@@ -318,6 +322,11 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
c_args.append(arg_name)
else:
c_args.append('%s._cptr' % arg_name)
+ if is_out(arg):
+ php_args.pop()
+ php_args.append(arg_name)
+ c_args.pop()
+ c_args.append(arg_name)
if php_args:
php_args = ', '.join(php_args)
@@ -331,7 +340,7 @@ function lassoRegisterIdWsf2DstService($prefix, $href) {
if m.docstring:
print >> self.fd, self.generate_docstring(m, mname, 4)
print >> self.fd, ' public function %s(%s) {' % (
- utils.format_underscore_as_camelcase(mname), php_args)
+ format_underscore_as_camelcase(mname), php_args)
if m.return_type == 'void':
print >> self.fd, ' %s($this->_cptr%s);' % (cname, c_args)
elif m.return_type in ('gint', 'int'):
diff --git a/bindings/php5/wrapper_source.py b/bindings/php5/wrapper_source.py
index 690c4adb..5775b7be 100644
--- a/bindings/php5/wrapper_source.py
+++ b/bindings/php5/wrapper_source.py
@@ -22,7 +22,7 @@
import sys
import os
-import utils
+from utils import *
class WrapperSource:
def __init__(self, binding_data, fd):
@@ -32,7 +32,7 @@ class WrapperSource:
self.src_dir = os.path.dirname(__file__)
def is_object(self, t):
- return t not in ['char*', 'const char*', 'gchar*', 'const gchar*', 'GList*', 'GHashTable*',
+ return t not in ['char*', 'const char*', 'gchar*', 'const gchar*', 'GList*', 'GHashTable*', 'GType',
'xmlNode*', 'int', 'gint', 'gboolean', 'const gboolean'] + self.binding_data.enums
def generate(self):
@@ -101,12 +101,81 @@ PHP_MSHUTDOWN_FUNCTION(lasso)
'''
+ def set_zval(self, zval_name, c_variable, type, free = False):
+ '''Emit code to set a zval* of name zval_name, from the value of the C variable called c_variable type, type.
+ '''
+ # first we free the previous value
+ p = (zval_name, c_variable)
+ q = { 'zval_name' : zval_name, 'c_variable' : c_variable }
+ print >> self.fd, ' zval_dtor(%s);' % zval_name
+ if is_pointer(type):
+ print >> self.fd, ' if (! %s) {' % c_variable
+ print >> self.fd, ' ZVAL_NULL(%s);' % zval_name
+ print >> self.fd, ' } else {'
+ if is_int(type, self.binding_data):
+ print >> self.fd, ' ZVAL_LONG(%s, %s);' % p
+ elif is_boolean(type):
+ print >> self.fd, ' ZVAL_BOOL(%s, %s);' % p
+ elif is_cstring(type):
+ print >> self.fd, ' ZVAL_STRING(%s, %s, 1);' % p
+ if free and not is_const(type):
+ print >> self.fd, 'g_free(%s)' % c_variable
+ elif arg_type(type) == 'xmlNode*':
+ print >> self.fd, '''\
+ {
+ char* xmlString = get_string_from_xml_node(%(c_variable)s);
+ if (xmlString) {
+ ZVAL_STRING(%(zval_name)s, xmlString, 0);
+ } else {
+ ZVAL_NULL(%(zval_name)s);
+ }
+ }
+''' % q
+ elif arg_type(type) == 'GList*':
+ elem_type = make_arg(element_type(type))
+ if not arg_type(elem_type):
+ raise Exception('unknown elem_type: ' + repr(type))
+ if is_cstring(elem_type):
+ function = 'set_array_from_list_of_strings'
+ free_function = 'free_glist(%(c_variable)s, (GFunc)free);'
+ elif arg_type(elem_type).startswith('xmlNode'):
+ function = 'set_array_from_list_of_xmlnodes'
+ free_function = 'free_glist(%(c_variable)s, (GFunc)xmlFree);'
+ elif is_object(elem_type):
+ function = 'set_array_from_list_of_objects'
+ free_function = 'g_list_free(%(c_variable)s);'
+ else:
+ raise Exception('unknown elem_type: ' + repr(type))
+ print >> self.fd, ' %s(%s, &%s);' % (function, c_variable, zval_name)
+ if free:
+ print >> self.fd, ' ', free_function % q
+ elif is_object(type):
+ print >> self.fd, '''\
+ if (G_IS_OBJECT(%(c_variable)s)) {
+ PhpGObjectPtr *obj = PhpGObjectPtr_New(G_OBJECT(%(c_variable)s));
+ ZEND_REGISTER_RESOURCE(%(zval_name)s, obj, le_lasso_server);
+ } else {
+ ZVAL_NULL(%(zval_name)s);
+ }''' % q
+ if free:
+ print >> self.fd, '''\
+ if (%(c_variable)s) {
+ g_object_unref(%(c_variable)s); // If constructor ref is off by one'
+ }''' % q
+
+ else:
+ raise Exception('unknown type: ' + repr(type) + unconstify(arg_type(type)))
+ if is_pointer(type):
+ print >> self.fd, ' }'
+
+
+
def return_value(self, vtype, options, free = False):
if vtype is None:
return
elif vtype == 'gboolean':
print >> self.fd, ' RETVAL_BOOL(return_c_value);'
- elif vtype in ['int', 'gint'] + self.binding_data.enums:
+ elif vtype in ['int', 'gint', 'GType', ] + self.binding_data.enums:
print >> self.fd, ' RETVAL_LONG(return_c_value);'
elif vtype in ('char*', 'gchar*'):
print >> self.fd, '''\
@@ -186,7 +255,12 @@ PHP_MSHUTDOWN_FUNCTION(lasso)
parse_tuple_args = []
for arg in m.args:
arg_type, arg_name, arg_options = arg
- if arg_type in ('char*', 'const char*', 'gchar*', 'const gchar*'):
+ if is_out(arg):
+ print >> self.fd, ' zval *php_out_%s = NULL;' % arg_name
+ print >> self.fd, ' %s %s;' % (var_type(arg), arg_name)
+ parse_tuple_format.append('z!')
+ parse_tuple_args.append('&php_out_%s' % arg_name)
+ elif arg_type in ('char*', 'const char*', 'gchar*', 'const gchar*'):
arg_type = arg_type.replace('const ', '')
parse_tuple_format.append('s!')
parse_tuple_args.append('&%s_str, &%s_len' % (arg_name, arg_name))
@@ -232,7 +306,9 @@ PHP_MSHUTDOWN_FUNCTION(lasso)
''' % (''.join(parse_tuple_format), parse_tuple_args)
for f, arg in zip(parse_tuple_format, m.args):
- if arg[0] == 'xmlNode*':
+ if is_out(arg):
+ continue
+ elif arg[0] == 'xmlNode*':
print >> self.fd, '''\
%(name)s = get_xml_node_from_string(%(name)s_str);''' % {'name': arg[1]}
elif f.startswith('s'):
@@ -259,12 +335,18 @@ PHP_MSHUTDOWN_FUNCTION(lasso)
print >> self.fd, '(%s)' % m.return_type,
else:
print >> self.fd, ' ',
- print >> self.fd, '%s(%s);' % (m.name, ', '.join([x[1] for x in m.args]))
+ print >> self.fd, '%s(%s);' % (m.name, ', '.join([ref_name(x) for x in m.args]))
# Free the converted arguments
for f, arg in zip(parse_tuple_format, m.args):
argtype, argname, argoptions = arg
- if argtype == 'xmlNode*':
+ if is_out(arg):
+ # export the returned variable
+ free = is_transfer_full(unref_type(arg))
+ print m
+ self.set_zval('php_out_%s' % argname, argname, unref_type(arg), free = free)
+ pass
+ elif argtype == 'xmlNode*':
print >> self.fd, ' xmlFree(%s);' % argname
elif f.startswith('a'):
elem_type = arg[2].get('elem_type')
@@ -289,7 +371,7 @@ PHP_MSHUTDOWN_FUNCTION(lasso)
print >> sys.stderr, 'E: GList argument : %s of %s, with type : %s' % (m_name, klassname, m_options.get('elem_type'))
return
- function_name = '%s_%s_get' % (klassname, utils.format_as_camelcase(m_name))
+ function_name = '%s_%s_get' % (klassname, format_as_camelcase(m_name))
print >> self.fd, '''PHP_FUNCTION(%s)
{''' % function_name
self.functions_list.append(function_name)
@@ -333,7 +415,7 @@ PHP_MSHUTDOWN_FUNCTION(lasso)
print >> sys.stderr, 'E: GList argument : %s of %s, with type : %s' % (m_name, klassname, m_options.get('elem_type'))
return
- function_name = '%s_%s_set' % (klassname, utils.format_as_camelcase(m_name))
+ function_name = '%s_%s_set' % (klassname, format_as_camelcase(m_name))
print >> self.fd, '''PHP_FUNCTION(%s)
{''' % function_name
self.functions_list.append(function_name)