| 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; | 
| 
 
sergei
2017/04/11 16:29:20
These global variables can also contribute into li
 
Wladimir Palant
2017/04/11 18:22:44
Ok, I can see your point. Yes, they are currently
 
 | 
| 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,54 +592,53 @@ 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);\ | 
| - BindingsInitializer::BindingsInitializer() | 
| + void InitializeBindings();\ | 
| + int main()\ | 
| + {\ | 
| + try\ | 
| + {\ | 
| + InitializeBindings();\ | 
| + 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;\ | 
| + }\ | 
| + void InitializeBindings() | 
| #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,\ | 
| String::value_type* data, String::size_type len)\ | 
| @@ -736,23 +729,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 +746,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); | 
| +} |