First stab at making NODE_MODULE(...) type safe.
Very simple, very portable, very verbose.
The function makeAdapter() picks the right partial specialization of InitAdapter<> based on the signature of the user supplied callback.
| { 'targets': [{'target_name': 'sketch', 'sources': ['sketch.cpp']}]} |
| #include <node.h> | |
| #include <iostream> | |
| //=== Node Country ============================================================= | |
| namespace node { | |
| typedef void (*addon_register_func_)( | |
| void * init_module, | |
| v8::Handle<v8::Object> exports, | |
| v8::Handle<v8::Value> module, | |
| v8::Handle<v8::Context> context, | |
| void * priv); | |
| namespace detail { | |
| template <typename T> | |
| inline | |
| T | |
| optional(v8::Handle<v8::Context> context, void * priv) { | |
| return context; | |
| }; | |
| template <> | |
| inline | |
| void * | |
| optional<void*>(v8::Handle<v8::Context> context, void * priv) { | |
| return priv; | |
| } | |
| template <typename F> struct InitAdapter; | |
| template <typename A0> | |
| struct InitAdapter<void (*)(A0)> { | |
| static const size_t arity = 1; | |
| typedef void (*init)(A0); | |
| static inline | |
| void | |
| registerAddon( void * f | |
| , v8::Handle<v8::Object> exports | |
| , v8::Handle<v8::Value> module | |
| , v8::Handle<v8::Context> context | |
| , void * priv) | |
| { | |
| reinterpret_cast<init>(f)(exports); | |
| } | |
| }; | |
| template <typename A0, typename A1> | |
| struct InitAdapter<void (*)(A0, A1)> { | |
| static const size_t arity = 2; | |
| typedef void (*init)(A0, A1); | |
| static inline | |
| void | |
| registerAddon( void * f | |
| , v8::Handle<v8::Object> exports | |
| , v8::Handle<v8::Value> module | |
| , v8::Handle<v8::Context> context | |
| , void * priv) | |
| { | |
| reinterpret_cast<init>(f)(exports, module); | |
| } | |
| }; | |
| template <typename A0, typename A1, typename A2> | |
| struct InitAdapter<void (*)(A0, A1, A2)> { | |
| static const size_t arity = 3; | |
| typedef void (*init)(A0, A1, A2); | |
| static inline | |
| void | |
| registerAddon( void * f | |
| , v8::Handle<v8::Object> exports | |
| , v8::Handle<v8::Value> module | |
| , v8::Handle<v8::Context> context | |
| , void * priv) | |
| { | |
| reinterpret_cast<init>(f)(exports, module, optional<A2>(context, priv)); | |
| } | |
| }; | |
| template <typename A0, typename A1, typename A2, typename A3> | |
| struct InitAdapter<void (*)(A0, A1, A2, A3)> { | |
| static const size_t arity = 4; | |
| typedef void (*init)(A0, A1, A2, A3); | |
| static inline | |
| void | |
| registerAddon( void * f | |
| , v8::Handle<v8::Object> exports | |
| , v8::Handle<v8::Value> module | |
| , v8::Handle<v8::Context> context | |
| , void * priv) | |
| { | |
| reinterpret_cast<init>(f)( | |
| exports | |
| , module | |
| , optional<A2>(context, priv) | |
| , optional<A3>(context, priv)); | |
| } | |
| }; | |
| template <typename F> | |
| node::addon_register_func_ | |
| makeAddonRegisterFunction(F f) { | |
| return InitAdapter<F>::registerAddon; | |
| } | |
| } // end of namespace detail | |
| } // end of namespace node | |
| //=== User Land ================================================================ | |
| void init1(v8::Handle<v8::Object> exports) { | |
| std::cout << "init(exports)" << std::endl; | |
| } | |
| void init2(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> module) { | |
| std::cout << "init(exports, module)" << std::endl; | |
| } | |
| void init3prv(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> module, void *priv) { | |
| std::cout << "init(exports, module, priv)" << std::endl; | |
| } | |
| void init3ctx(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> module, v8::Handle<v8::Context> context) { | |
| std::cout << "init(exports, module, context)" << std::endl; | |
| } | |
| void init4cp(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> module, v8::Handle<v8::Context> context, void * priv) { | |
| std::cout << "init(exports, module, context, priv)" << std::endl; | |
| } | |
| // generic, baby... | |
| void init4pc(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> module, void * priv, v8::Handle<v8::Context> context) { | |
| std::cout << "init(exports, module, priv, context)" << std::endl; | |
| } | |
| void init( v8::Handle<v8::Object> exports | |
| , v8::Handle<v8::Value> module | |
| , v8::Handle<v8::Context> context | |
| , void *priv) | |
| { | |
| // testing... | |
| node::addon_register_func_ f1 = node::detail::makeAddonRegisterFunction(init1); | |
| f1(reinterpret_cast<void*>(init1), exports, module, context, priv); | |
| node::addon_register_func_ f2 = node::detail::makeAddonRegisterFunction(init2); | |
| f2(reinterpret_cast<void*>(init2), exports, module, context, priv); | |
| node::addon_register_func_ f3 = node::detail::makeAddonRegisterFunction(init3prv); | |
| f3(reinterpret_cast<void*>(init3prv), exports, module, context, priv); | |
| node::addon_register_func_ f4 = node::detail::makeAddonRegisterFunction(init3ctx); | |
| f4(reinterpret_cast<void*>(init3ctx), exports, module, context, priv); | |
| node::addon_register_func_ f5 = node::detail::makeAddonRegisterFunction(init4cp); | |
| f5(reinterpret_cast<void*>(init4cp), exports, module, context, priv); | |
| node::addon_register_func_ f6 = node::detail::makeAddonRegisterFunction(init4pc); | |
| f6(reinterpret_cast<void*>(init4pc), exports, module, context, priv); | |
| } | |
| NODE_MODULE_CONTEXT_AWARE(sketch, init) |
| require('./build/Release/sketch'); |