| Index: compiled/bindings.ipp |
| =================================================================== |
| --- a/compiled/bindings.ipp |
| +++ b/compiled/bindings.ipp |
| @@ -17,16 +17,17 @@ |
| #pragma once |
| #include <cstddef> |
| #include <cstdint> |
| #include <cstdio> |
| #include <cstdlib> |
| #include <exception> |
| +#include <functional> |
| #include <map> |
| #include <string> |
| #include <type_traits> |
| #include <utility> |
| #include <vector> |
| #include <emscripten.h> |
| @@ -303,22 +304,24 @@ namespace bindings_internal |
| }; |
| struct ClassInfo |
| { |
| ClassInfo* baseClass; |
| std::string name; |
| std::vector<PropertyInfo> properties; |
| std::vector<MethodInfo> methods; |
| - std::vector<FunctionInfo> initializers; |
| DifferentiatorInfo subclass_differentiator; |
| ptrdiff_t ref_counted_offset; |
| }; |
| + typedef std::function<void()> CustomGenerator; |
| + |
| std::map<TYPEID, ClassInfo> classes; |
| + std::vector<CustomGenerator> customGenerators; |
| void register_class(const char* name, TYPEID classID, TYPEID baseClassID, |
| ptrdiff_t ref_counted_offset) |
| { |
| auto it = classes.find(classID); |
| if (it != classes.end()) |
| throw std::runtime_error(std::string("Duplicate definition for class ") + name); |
| @@ -363,25 +366,16 @@ namespace bindings_internal |
| throw std::runtime_error(std::string("Method defined on unknown class: ") + name); |
| MethodInfo methodInfo; |
| methodInfo.name = name; |
| methodInfo.call = call; |
| it->second.methods.push_back(methodInfo); |
| } |
| - void register_initializer(TYPEID classID, const FunctionInfo& call) |
| - { |
| - auto it = classes.find(classID); |
| - if (it == classes.end()) |
| - throw std::runtime_error("Initializer defined on unknown class"); |
| - |
| - it->second.initializers.push_back(call); |
| - } |
| - |
| void register_differentiator(TYPEID classID, size_t offset, |
| std::vector<std::pair<int, std::string>>& mapping) |
| { |
| auto it = classes.find(classID); |
| if (it == classes.end()) |
| throw std::runtime_error("Subclass differentiator defined on unknown class"); |
| if (it->second.subclass_differentiator.offset != SIZE_MAX) |
| @@ -598,53 +592,54 @@ namespace bindings_internal |
| for (const auto& item : cls.methods) |
| { |
| std::string obj("exports." + cls.name); |
| if (item.call.instance_function) |
| obj += ".prototype"; |
| printf("%s.%s = %s;\n", obj.c_str(), item.name.c_str(), |
| wrapCall(item.call).c_str()); |
| } |
| - |
| - for (const auto& item : cls.initializers) |
| - printf("%s()\n", item.name); |
| } |
| void printBindings() |
| { |
| printHelpers(); |
| for (const auto& item : classes) |
| printClass(item.second); |
| + |
| + for (const auto& item : customGenerators) |
| + item(); |
| } |
| } |
| #if defined(PRINT_BINDINGS) |
| // Bindings generation step: collect bindings information and print |
| // corresponding JS code. |
| #define EMSCRIPTEN_BINDINGS \ |
| struct BindingsInitializer {\ |
| BindingsInitializer();\ |
| - BindingsInitializer(bool dummy)\ |
| - {\ |
| - try\ |
| - {\ |
| - BindingsInitializer();\ |
| - bindings_internal::printBindings();\ |
| - }\ |
| - catch (const std::exception& e)\ |
| - {\ |
| - EM_ASM_ARGS(\ |
| - console.error("Error occurred generating JavaScript bindings: " +\ |
| - Module.AsciiToString($0)), e.what()\ |
| - );\ |
| - abort();\ |
| - }\ |
| - }\ |
| - } BindingsInitializer_instance(true);\ |
| + };\ |
|
sergei
2017/03/30 11:09:17
I would make it a simple function `void Initialize
Wladimir Palant
2017/03/30 12:58:58
Done.
|
| + int main(void)\ |
|
sergei
2017/03/30 11:09:17
In C++ there is no need for specifying of void in
sergei
2017/03/30 11:09:17
Do you mind to consider in future moving of such C
Wladimir Palant
2017/03/30 12:58:58
Done.
Wladimir Palant
2017/03/30 12:58:58
Not sure what you mean. This code is inside bindin
sergei
2017/04/04 14:49:30
I mean it would be better to have this code in ano
Wladimir Palant
2017/04/04 15:41:48
But we are not compiling an executable, it's not s
sergei
2017/04/11 16:29:20
I didn't mean to append a cpp with main to SOURCE_
Wladimir Palant
2017/04/11 18:22:44
Let's do this in a follow-up, I'll file an issue.
|
| + {\ |
| + try\ |
| + {\ |
| + struct BindingsInitializer instance;\ |
|
sergei
2017/03/30 11:09:17
Why did you need to add struct here?
Wladimir Palant
2017/03/30 12:58:57
This is a InitializeBindings() call now - this was
|
| + bindings_internal::printBindings();\ |
| + }\ |
| + catch (const std::exception& e)\ |
| + {\ |
| + EM_ASM_ARGS(\ |
| + console.error("Error occurred generating JavaScript bindings: " +\ |
| + Module.AsciiToString($0)), e.what()\ |
| + );\ |
| + abort();\ |
| + }\ |
| + return 0;\ |
| + }\ |
| BindingsInitializer::BindingsInitializer() |
| #else |
| // Actual compilation step: ignore bindings information but define some |
| // exported helper functions necessary for the bindings. |
| #define EMSCRIPTEN_BINDINGS \ |
| extern "C"\ |
| {\ |
| void EMSCRIPTEN_KEEPALIVE InitString(DependentString* str,\ |
| @@ -736,23 +731,16 @@ public: |
| template<typename ReturnType, typename... Args> |
| const class_& class_function(const char* name, ReturnType (*method)(Args...)) const |
| { |
| bindings_internal::register_method( |
| bindings_internal::TypeInfo<ClassType>(), name, method); |
| return *this; |
| } |
| - const class_& class_initializer(void (*function)()) const |
| - { |
| - bindings_internal::register_initializer( |
| - bindings_internal::TypeInfo<ClassType>(), function); |
| - return *this; |
| - } |
| - |
| template<typename ReturnType, |
| typename std::enable_if<std::is_convertible<ReturnType, int32_t>::value>::type* = nullptr> |
| const class_& subclass_differentiator(ReturnType ClassType::* member, |
| std::initializer_list<std::pair<ReturnType, const char*>> list) const |
| { |
| ClassType* instance = nullptr; |
| size_t offset = (char*)&(instance->*member) - (char*)instance; |
| @@ -760,8 +748,13 @@ public: |
| for (const auto& item : list) |
| mapping.emplace_back(item.first, item.second); |
| bindings_internal::register_differentiator( |
| bindings_internal::TypeInfo<ClassType>(), offset, mapping); |
| return *this; |
| } |
| }; |
| + |
| +void custom_generator(bindings_internal::CustomGenerator generator) |
| +{ |
| + bindings_internal::customGenerators.push_back(generator); |
| +} |