aboutsummaryrefslogtreecommitdiff
path: root/tools/bindings_generator.py
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2011-08-06 21:46:55 -0700
committerAlon Zakai <alonzakai@gmail.com>2011-08-06 21:46:55 -0700
commitb2d49aa9a76305e9c50dafbc436c53099a27dd19 (patch)
treec19e7138df07020d3b6756d22e10083faf0ea4cd /tools/bindings_generator.py
parentef023c234b8c5c9620aff2e56f359c95529b6e87 (diff)
better handling of abstract base classes in bindings generator
Diffstat (limited to 'tools/bindings_generator.py')
-rwxr-xr-xtools/bindings_generator.py67
1 files changed, 41 insertions, 26 deletions
diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py
index ffbb1359..fe230c43 100755
--- a/tools/bindings_generator.py
+++ b/tools/bindings_generator.py
@@ -102,15 +102,16 @@ for classname, clazz in classes.iteritems():
method['num_args'] = set(range(default_param-1, len(args)+1))
print 'zz ', classname, 'has num_args of', method['num_args']
+ method['returns_text'] = method['returns']
if method['static']:
- method['returns'] = method['returns'].replace('static', '')
+ method['returns_text'] = method['returns_text'].replace('static', '')
# Fill in some missing stuff
- if method.get('returns_const'): method['returns'] = 'const ' + method['returns']
+ if method.get('returns_const'): method['returns_text'] = 'const ' + method['returns_text']
if method.get('returns_pointer'):
- while method['returns'].count('*') < method['returns_pointer']:
- method['returns'] += '*'
- if method.get('returns_reference'): method['returns'] += '&'
+ while method['returns_text'].count('*') < method['returns_pointer']:
+ method['returns_text'] += '*'
+ if method.get('returns_reference'): method['returns_text'] += '&'
# Explore all functions we need to generate, including parent classes, handling of overloading, etc.
@@ -126,7 +127,7 @@ for classname, clazz in parsed.classes.iteritems():
if method['name'] not in clazz['final_methods']:
clazz['final_methods'][method['name']] = {}
- for key in ['name', 'constructor', 'static', 'returns', 'destructor', 'pure_virtual']:
+ for key in ['name', 'constructor', 'static', 'returns', 'returns_text', 'destructor', 'pure_virtual']:
clazz['final_methods'][method['name']][key] = method[key]
clazz['final_methods'][method['name']]['num_args'] = method['num_args'].copy()
clazz['final_methods'][method['name']]['parameters'] = method['parameters'][:]
@@ -180,6 +181,10 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
inherited = generating_classname_head != classname_head
+ if clazz['abstract']:
+ # For abstract base classes, add a function definition on top. There is no constructor
+ gen_js.write('\nfunction ' + generating_classname_head + '(){}\n')
+
for method in clazz['final_methods'].itervalues():
mname = method['name']
if classname_head + '::' + mname in ignored: continue
@@ -189,10 +194,11 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
destructor = method['destructor']
static = method['static']
- print "zz generating:", generating_classname, classname, mname, constructor, method['returns']
+ print "zz generating:", generating_classname, classname, mname, constructor, method['returns'], method['returns_text']
if destructor: continue
if constructor and inherited: continue
+ if constructor and clazz['abstract']: continue # do not generate constructors for abstract base classes
skip = False
for i in range(len(args)):
@@ -221,7 +227,7 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
if skip:
continue
- ret = ((classname + ' *') if constructor else method['returns']).replace('virtual ', '')
+ ret = ((classname + ' *') if constructor else method['returns_text'])#.replace('virtual ', '')
callprefix = 'new ' if constructor else ('self->' if not static else (classname + '::'))
actualmname = ''
@@ -281,8 +287,15 @@ def generate_class(generating_classname, classname, clazz): # TODO: deprecate ge
calls += '''this.ptr = _%s_p%d(%s);
''' % (fullname, i, ', '.join(justargs[:i]))
else:
- calls += '''%s_%s_p%d(%s);
-''' % ('return ' if ret != 'void' else '', fullname, i, ', '.join((['this.ptr'] if need_self else []) + justargs[:i]))
+ return_value = '''_%s_p%d(%s)''' % (fullname, i, ', '.join((['this.ptr'] if need_self else []) + justargs[:i]))
+ print 'zz making return', classname, method['name'], method['returns'], return_value
+ if method['returns'] in classes:
+ # Generate a wrapper
+ calls += '{ var ptr = ' + return_value + '; if (!ptr) return null; var ret = Object.create(' + method['returns'] + '.prototype); ret.ptr = ptr; return ret; }'
+ else:
+ # Normal return
+ calls += ('return ' if ret != 'void' else '') + return_value + ';'
+ calls += '\n'
print 'Maekin:', classname, generating_classname, mname, mname_suffixed
if constructor:
@@ -307,7 +320,7 @@ function %s(%s) {
%s
%s
}
-''' % (generating_classname, mname_suffixed, ', '.join(justargs), argfixes, calls)
+''' % (generating_classname_head, mname_suffixed, ', '.join(justargs), argfixes, calls)
js_text = js_text.replace('\n\n', '\n').replace('\n\n', '\n')
gen_js.write(js_text)
@@ -317,7 +330,8 @@ function %s(%s) {
for classname, clazz in classes.iteritems():
if any([name in ignored for name in classname.split('::')]): continue
- # Nothing to generate for pure virtual classes
+ # Nothing to generate for pure virtual classes XXX actually this is not so. We do need to generate wrappers for returned objects,
+ # they are of a concrete class of course, but an known one, so we create a wrapper for an abstract base class.
def check_pure_virtual(clazz, progeny):
#if not clazz.get('inherits'): return False # If no inheritance info, not a class, this is a CppHeaderParser struct
@@ -340,27 +354,28 @@ for classname, clazz in classes.iteritems():
print 'zz ignoring pure virtual class', classname, 'due to', method['name']
return True
- if check_pure_virtual(clazz, []):
- continue
+ clazz['abstract'] = check_pure_virtual(clazz, [])
+ #if check_pure_virtual(clazz, []):
+ # continue
# Add a constructor if none exist
has_constructor = False
for method in clazz['methods']:
- mname = method['name']
has_constructor = has_constructor or (method['constructor'] and not method['destructor'])
-
+
print 'zz', classname, 'has constructor?', has_constructor
-
+
if not has_constructor:
- print 'zz no constructor for', classname, 'so ignoring'
- continue
-
- clazz['methods'] = [{
- 'name': classname,
- 'parameters': [],
- 'pure_virtual': False,
- 'destructor': False,
- }] + clazz['methods']
+ if not clazz['abstract']:
+ print 'zz no constructor for', classname, 'and not abstract, so ignoring'
+ continue
+
+ #clazz['methods'] = [{
+ # 'name': classname,
+ # 'parameters': [],
+ # 'pure_virtual': False,
+ # 'destructor': False,
+ #}] + clazz['methods']
generate_class(classname, classname, clazz)