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'); |