aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authormax99x <max99x@gmail.com>2011-07-06 16:37:28 +0300
committermax99x <max99x@gmail.com>2011-07-06 16:37:28 +0300
commitdedb83b9e15591893e1b30220c721e447518f5d9 (patch)
tree87068307ade1fbcff662fcef5e943d944f4f7374 /tools
parent13ac46b2c9be4aa17319c450a15ed96b71e091d7 (diff)
parente84f1845f1a96ecfda4f1ffc0ba2052dc7c8c86d (diff)
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'tools')
-rw-r--r--tools/bindings_generator.py135
-rwxr-xr-xtools/emmaken.py2
2 files changed, 136 insertions, 1 deletions
diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py
new file mode 100644
index 00000000..81d1a0fe
--- /dev/null
+++ b/tools/bindings_generator.py
@@ -0,0 +1,135 @@
+'''
+Use CppHeaderParser to parse some C++ headers, and generate binding code for them.
+
+Usage:
+ bindings_generator.py BASENAME HEADER1 HEADER2 ...
+
+ BASENAME is the name used for output files (with added suffixes).
+ HEADER1 etc. are the C++ headers to parse
+
+We generate the following:
+
+ * BASENAME.c: C bindings file, with generated C wrapper functions. You will
+ need to build this with your project, and make sure it compiles
+ properly by adding the proper #includes etc. You can also just
+ #include this file itself in one of your existing project files.
+
+ * BASENAME.js: JavaScript bindings file, with generated JavaScript wrapper
+ objects. This is a high-level wrapping, using native JS classes.
+'''
+
+import os, sys, glob
+
+abspath = os.path.abspath(os.path.dirname(__file__))
+def path_from_root(*pathelems):
+ return os.path.join(os.path.sep, *(abspath.split(os.sep)[:-1] + list(pathelems)))
+exec(open(path_from_root('tools', 'shared.py'), 'r').read())
+
+# Find ply and CppHeaderParser
+sys.path = [path_from_root('third_party', 'ply'), path_from_root('third_party', 'CppHeaderParser')] + sys.path
+import CppHeaderParser
+
+#print glob.glob(path_from_root('tests', 'bullet', 'src', 'BulletCollision', 'CollisionDispatch', '*.h'))
+
+basename = sys.argv[1]
+
+# First pass - read everything
+
+classes = {}
+
+for header in sys.argv[2:]:
+ #[('tests', 'bullet', 'src', 'BulletCollision/CollisionDispatch/btCollisionWorld.h')]:
+ parsed = CppHeaderParser.CppHeader(header)
+ #header = CppHeaderParser.CppHeader(path_from_root('tests', 'bullet', 'src', 'btBulletDynamicsCommon.h'))
+ #print header.classes.keys()
+ #print dir(header.classes['btCollisionShape'])
+ #print header.classes['btCollisionWorld']['methods']['public']
+ for cname, clazz in parsed.classes.iteritems():
+ if len(clazz['methods']['public']) > 0: # Do not notice stub classes
+ print 'Seen', cname
+ classes[cname] = clazz
+
+# Second pass - generate bindings
+
+funcs = []
+
+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
+
+ for method in clazz['methods']['public']:
+ #print ' ', method['name'], method
+
+ mname = method['name']
+ args = method['parameters']
+ constructor = mname == cname
+
+ # 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
+
+ gen_c.write('''
+%s emscripten_bind_%s(%s) {
+ return %s%s(%s);
+}
+''' % (ret, fullname, typedargs, callprefix, mname, justargs))
+
+ funcs.append('emscripten_bind_' + fullname)
+
+ # JS
+
+ if constructor:
+ gen_js.write('''
+function %s(%s) {
+ this.ptr = _emscripten_bind_%s(%s);
+}
+''' % (cname + (str(constructor_counter) if constructor_counter > 0 else ''), justargs, fullname, justargs))
+ constructor_counter += 1
+ else: # TODO: handle case of multiple constructors
+ gen_js.write('''
+%s.prototype.%s = function(%s) {
+ %s_emscripten_bind_%s(this.ptr%s);
+}
+''' % (cname, mname, justargs, 'return ' if ret != 'void' else '', fullname, (', ' if len(justargs) > 0 else '') + justargs))
+
+
+# Finish up
+
+gen_c.write('''
+}
+
+#include <stdio.h>
+
+struct EmscriptenEnsurer
+{
+ EmscriptenEnsurer() {
+ // Actually use the binding functions, so DFE will not eliminate them
+ int sum = 0;
+ void *seen = (void*)%s;
+''' % funcs[0])
+
+for func in funcs[1:]:
+ gen_c.write(''' sum += (void*)%s == seen;
+''' % func)
+
+gen_c.write(''' printf("(%d)\\n", sum);
+ }
+};
+
+EmscriptenEnsurer emscriptenEnsurer;
+''')
+
+gen_c.close()
+gen_js.close()
+
diff --git a/tools/emmaken.py b/tools/emmaken.py
index 0d33c525..dea8194e 100755
--- a/tools/emmaken.py
+++ b/tools/emmaken.py
@@ -85,7 +85,7 @@ try:
sys.argv = sys.argv[:-1]
CC_ARG_SKIP = ['-O1', '-O2', '-O3']
- CC_ADDITIONAL_ARGS = ['-m32', '-U__i386__', '-U__x86_64__', '-U__SSE__', '-UX87_DOUBLE_ROUNDING', '-UHAVE_GCC_ASM_FOR_X87']
+ CC_ADDITIONAL_ARGS = ['-m32', '-U__i386__', '-U__x86_64__', '-U__i386', '-U__x86_64', '-U__SSE__', '-U__SSE2__', '-UX87_DOUBLE_ROUNDING', '-UHAVE_GCC_ASM_FOR_X87']
ALLOWED_LINK_ARGS = ['-f', '-help', '-o', '-print-after', '-print-after-all', '-print-before',
'-print-before-all', '-time-passes', '-v', '-verify-dom-info', '-version' ]
DISALLOWED_LINK_ARGS = []#['rc']