aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xtools/bindings_generator.py81
1 files changed, 70 insertions, 11 deletions
diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py
index 1e34c11f..076c1106 100755
--- a/tools/bindings_generator.py
+++ b/tools/bindings_generator.py
@@ -94,6 +94,7 @@ for classname, clazz in parsed.classes.iteritems():
print 'zz see', classname
classes[classname] = clazz
clazz['methods'] = clazz['methods']['public'] # CppHeaderParser doesn't have 'public' etc. in structs. so equalize to that
+
if '::' in classname:
assert classname.count('::') == 1
parents[classname.split('::')[1]] = classname.split('::')[0]
@@ -147,6 +148,49 @@ for classname, clazz in classes.iteritems():
print 'zz %s::%s gets %s and returns %s' % (classname, method['name'], str([arg['type'] for arg in method['parameters']]), method['returns_text'])
+ # Add getters/setters for public members
+ for prop in clazz['properties']['public']:
+ if classname + '::' + prop['name'] in ignored: continue
+ if prop.get('array_dimensions'):
+ print 'zz warning: ignoring getter/setter for array', classname + '::' + prop['name']
+ continue
+ type_ = prop['type'].replace('mutable ', '')#.replace(' ', '')
+ if '<' in prop['name'] or '<' in type_:
+ print 'zz warning: ignoring getter/setter for templated class', classname + '::' + prop['name']
+ continue
+ reference = type_ in classes # a raw struct or class as a prop means we need to work with a ref
+ clazz['methods'].append({
+ 'getter': True,
+ 'name': 'get_' + prop['name'],
+ 'constructor': False,
+ 'destructor': False,
+ 'static': False,
+ 'returns': type_.replace(' *', '').replace('*', ''),
+ 'returns_text': type_ + ('&' if reference else ''),
+ 'returns_reference': reference,
+ 'returns_pointer': '*' in type_,
+ 'pure_virtual': False,
+ 'num_args': set([0]),
+ 'parameters': [],
+ })
+ clazz['methods'].append({
+ 'setter': True,
+ 'name': 'set_' + prop['name'],
+ 'constructor': False,
+ 'destructor': False,
+ 'static': False,
+ 'returns': 'void',
+ 'returns_text': 'void',
+ 'returns_reference': False,
+ 'returns_pointer': False,
+ 'pure_virtual': False,
+ 'num_args': set([1]),
+ 'parameters': [{
+ 'type': type_ + ('&' if reference else ''),
+ 'name': 'value',
+ }],
+ })
+
# Explore all functions we need to generate, including parent classes, handling of overloading, etc.
def clean_type(t):
@@ -173,8 +217,9 @@ for classname, clazz in parsed.classes.iteritems():
if method['name'] not in clazz['final_methods']:
copied = clazz['final_methods'][method['name']] = {}
- for key in ['name', 'constructor', 'static', 'returns', 'returns_text', 'returns_reference', 'returns_pointer', 'destructor', 'pure_virtual']:
- copied[key] = method[key]
+ for key in ['name', 'constructor', 'static', 'returns', 'returns_text', 'returns_reference', 'returns_pointer', 'destructor', 'pure_virtual',
+ 'getter', 'setter']:
+ copied[key] = method.get(key)
copied['num_args'] = method['num_args'].copy()
copied['origin'] = subclass
copied['parameters'] = [];
@@ -248,7 +293,9 @@ gen_c.write('extern "C" {\n')
# Use this when calling a binding function when you want to pass a null pointer.
# Having this object saves us needing to do checks for the object being null each time in the bindings code.
gen_js.write('''
-var NULL = { ptr: 0 };
+function wrapPointer(ptr) { return { ptr: ptr } };
+this['wrapPointer'] = wrapPointer;
+this['NULL'] = wrapPointer(0);
''')
def generate_wrapping_code(classname):
@@ -324,11 +371,13 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
ret = ((classname + ' *') if constructor else method['returns_text'])#.replace('virtual ', '')
callprefix = 'new ' if constructor else ('self->' if not static else (classname + '::'))
- actualmname = ''
+ actualmname = '' # mname used in C
if '__operator__' in mname:
continue # TODO: operators
else:
actualmname = classname if constructor else (method.get('truename') or mname)
+ if method.get('getter') or method.get('setter'):
+ actualmname = actualmname[4:]
need_self = not constructor and not static
typedargs = ([] if not need_self else [classname + ' * self']) + map(lambda arg: arg['type'] + ' ' + arg['name'], args)
@@ -353,17 +402,27 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
# C
for i in method['num_args']:
-
# If we are returning a *copy* of an object, we return instead to a ref of a static held here. This seems the best compromise
staticize = not constructor and ret.replace(' ', '') != 'void' and method['returns'] in classes and (not method['returns_reference'] and not method['returns_pointer'])
gen_c.write('''
-%s %s_p%d(%s) {''' % (ret if not staticize else (ret + '&'), fullname, i, ', '.join(typedargs[:i + (0 if not need_self else 1)])))
+%s %s_p%d(%s) {''' % (ret if not staticize else (ret + '&'), fullname, i,
+ ', '.join(typedargs[:i + (0 if not need_self else 1)])))
if not staticize:
- gen_c.write('''
+ if method.get('getter'):
+ gen_c.write('''
+ return self->%s;
+''' % actualmname)
+ elif method.get('setter'):
+ gen_c.write('''
+ self->%s = value;
+''' % actualmname)
+ else: # normal method
+ gen_c.write('''
%s%s%s(%s);
-}''' % ('return ' if ret.replace(' ', '') != 'void' else '',
- callprefix, actualmname,
- ', '.join(justargs[:i])))
+''' % ('return ' if ret.replace(' ', '') != 'void' else '',
+ callprefix, actualmname, ', '.join(justargs[:i])))
+
+ gen_c.write('}')
else:
gen_c.write('''
static %s ret = %s%s(%s);
@@ -407,7 +466,7 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
print 'zz making return', classname, method['name'], method['returns'], return_value
if method['returns'] in classes:
# Generate a wrapper
- calls += 'return %s__wrap__(%s);' % (method['returns'], return_value)
+ calls += 'return %s__wrap__(%s);' % (method['returns'].split('::')[-1], return_value)
else:
# Normal return
calls += ('return ' if ret != 'void' else '') + return_value + ';'