Skip to content

Instantly share code, notes, and snippets.

@agnat
Last active August 29, 2015 14:10
Show Gist options
  • Save agnat/1f70bd870258918bf429 to your computer and use it in GitHub Desktop.
Save agnat/1f70bd870258918bf429 to your computer and use it in GitHub Desktop.
NODE_MODULE(...): Type safe init dispatch sketch

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');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment