aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/bindings_generator.py69
1 files changed, 51 insertions, 18 deletions
diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py
index 81d1a0fe..359244ad 100644
--- a/tools/bindings_generator.py
+++ b/tools/bindings_generator.py
@@ -16,6 +16,12 @@ We generate the following:
* BASENAME.js: JavaScript bindings file, with generated JavaScript wrapper
objects. This is a high-level wrapping, using native JS classes.
+
+The C bindings file is basically a tiny C wrapper around the C++ code.
+It's only purpose is to make it easy to access the C++ code in the JS
+bindings, and to prevent DFE from removing the code we care about. The
+JS bindings do more serious work, creating class structures in JS and
+linking them to the C bindings.
'''
import os, sys, glob
@@ -50,62 +56,89 @@ for header in sys.argv[2:]:
classes[cname] = clazz
# Second pass - generate bindings
+# TODO: Bind virtual functions using dynamic binding in the C binding code
-funcs = []
+funcs = {} # name -> # of copies in the original, and originalname in a copy
gen_c = open(basename + '.c', 'w')
gen_js = open(basename + '.js', 'w')
gen_c.write('extern "C" {\n')
-for cname, clazz in classes.iteritems():
- print 'Generating', cname
- # TODO: Generate all parent class (recursively) data too
-
- constructor_counter = 0
+def generate_class(generating_cname, cname, clazz):
+ inherited = generating_cname != cname
for method in clazz['methods']['public']:
- #print ' ', method['name'], method
+ print ' ', method['name'], method
mname = method['name']
args = method['parameters']
constructor = mname == cname
+ if constructor and inherited: continue
+
# C
ret = (cname + ' *') if constructor else method['rtnType']
callprefix = 'new ' if constructor else 'self->'
typedargs = ', '.join( ([] if constructor else [cname + ' * self']) + map(lambda arg: arg['type'] + ' ' + arg['name'], args) )
justargs = ', '.join(map(lambda arg: arg['name'], args))
- fullname = cname + '__' + mname
+ fullname = 'emscripten_bind_' + generating_cname + '__' + mname
+ generating_cname_suffixed = generating_cname
+ mname_suffixed = mname
+ count = funcs.setdefault(fullname, 0)
+ funcs[fullname] += 1
+
+ # handle overloading
+ if count > 0:
+ suffix = '_' + str(count+1)
+ funcs[fullname + suffix] = fullname # this should never change
+ fullname += suffix
+ mname_suffixed += suffix
+ if constructor:
+ generating_cname_suffixed += suffix
gen_c.write('''
-%s emscripten_bind_%s(%s) {
+%s %s(%s) {
return %s%s(%s);
}
''' % (ret, fullname, typedargs, callprefix, mname, justargs))
- funcs.append('emscripten_bind_' + fullname)
-
# JS
if constructor:
- gen_js.write('''
+ dupe = type(funcs[fullname]) is str
+ if not dupe:
+ gen_js.write('''
function %s(%s) {
- this.ptr = _emscripten_bind_%s(%s);
+ this.ptr = _%s(%s);
}
-''' % (cname + (str(constructor_counter) if constructor_counter > 0 else ''), justargs, fullname, justargs))
- constructor_counter += 1
- else: # TODO: handle case of multiple constructors
+''' % (generating_cname_suffixed, justargs, fullname, justargs))
+ else:
+ gen_js.write('''
+function %s(%s) {
+ this.ptr = _%s(%s);
+}
+%s.prototype = %s.prototype;
+''' % (generating_cname_suffixed, justargs, fullname, justargs, generating_cname_suffixed, cname))
+ else:
gen_js.write('''
%s.prototype.%s = function(%s) {
- %s_emscripten_bind_%s(this.ptr%s);
+ %s_%s(this.ptr%s);
}
-''' % (cname, mname, justargs, 'return ' if ret != 'void' else '', fullname, (', ' if len(justargs) > 0 else '') + justargs))
+''' % (generating_cname, mname_suffixed, justargs, 'return ' if ret != 'void' else '', fullname, (', ' if len(justargs) > 0 else '') + justargs))
+for cname, clazz in classes.iteritems():
+ generate_class(cname, cname, clazz)
+
+ # In addition, generate all methods of parent classes. We do not inherit in JS (how would we do multiple inheritance etc.?)
+ for parent in clazz['inherits']:
+ generate_class(cname, parent['class'], classes[parent['class']])
# Finish up
+funcs = funcs.keys()
+
gen_c.write('''
}