diff options
-rw-r--r-- | src/embind/embind.js | 23 | ||||
-rw-r--r-- | system/include/emscripten/bind.h | 64 |
2 files changed, 83 insertions, 4 deletions
diff --git a/src/embind/embind.js b/src/embind/embind.js index 6ec07cd9..23248335 100644 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -1,4 +1,4 @@ -/*global Module*/ +/*global Module, asm*/ /*global _malloc, _free, _memcpy*/ /*global FUNCTION_TABLE, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64*/ /*global readLatin1String*/ @@ -708,10 +708,27 @@ function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cp return invokerFunction; } -function __embind_register_function(name, argCount, rawArgTypesAddr, rawInvoker, fn) { +function requireFunction(signature, rawFunction) { + signature = readLatin1String(signature); + var fp; + if (typeof FUNCTION_TABLE === "undefined") { + // asm.js style + fp = asm['FUNCTION_TABLE_' + signature](rawFunction); + } else { + fp = FUNCTION_TABLE[rawFunction]; + } + + if (typeof fp !== "function") { + throwBindingError("unknown function pointer with signature " + signature + ": " + rawFunction); + } + return fp; +} + +function __embind_register_function(name, argCount, rawArgTypesAddr, signature, rawInvoker, fn) { var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr); name = readLatin1String(name); - rawInvoker = FUNCTION_TABLE[rawInvoker]; + + rawInvoker = requireFunction(signature, rawInvoker); exposePublicSymbol(name, function() { throwUnboundTypeError('Cannot call ' + name + ' due to unbound types', argTypes); diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 872f279b..8a8b7d69 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -20,6 +20,8 @@ namespace emscripten { namespace internal { typedef long GenericEnumValue; + typedef void (*GenericFunction)(); + // Implemented in JavaScript. Don't call these directly. extern "C" { void _embind_fatal_error( @@ -70,6 +72,7 @@ namespace emscripten { const char* name, unsigned argCount, TYPEID argTypes[], + const char* signature, GenericFunction invoker, GenericFunction function); @@ -291,6 +294,63 @@ namespace emscripten { } //////////////////////////////////////////////////////////////////////////////// + // SignatureCode, SignatureString + //////////////////////////////////////////////////////////////////////////////// + + namespace internal { + template<typename T> + struct SignatureCode { + static constexpr char get() { + return 'i'; + } + }; + + template<> + struct SignatureCode<void> { + static constexpr char get() { + return 'v'; + } + }; + + template<> + struct SignatureCode<float> { + static constexpr char get() { + return 'd'; + } + }; + + template<> + struct SignatureCode<double> { + static constexpr char get() { + return 'd'; + } + }; + + template<typename... T> + struct SignatureString; + + template<> + struct SignatureString<> { + char c = 0; + }; + + template<typename First, typename... Rest> + struct SignatureString<First, Rest...> { + constexpr SignatureString() + : c(SignatureCode<First>::get()) + {} + char c; + SignatureString<Rest...> rest; + }; + + template<typename Return, typename... Args> + const char* getSignature(Return (*)(Args...)) { + static constexpr SignatureString<Return, Args...> sig; + return &sig.c; + } + } + + //////////////////////////////////////////////////////////////////////////////// // FUNCTIONS //////////////////////////////////////////////////////////////////////////////// @@ -302,11 +362,13 @@ namespace emscripten { void function(const char* name, ReturnType (*fn)(Args...), Policies...) { using namespace internal; typename WithPolicies<Policies...>::template ArgTypeList<ReturnType, Args...> args; + auto invoker = &Invoker<ReturnType, Args...>::invoke; _embind_register_function( name, args.count, args.types, - reinterpret_cast<GenericFunction>(&Invoker<ReturnType, Args...>::invoke), + getSignature(invoker), + reinterpret_cast<GenericFunction>(invoker), reinterpret_cast<GenericFunction>(fn)); } |