内置C++模块的注册
2020-03-27 本文已影响0人
orgcheng
node.cc类的InitializeNodeWithArgs方法中,调用了binding::RegisterBuiltinModules();方法,主要是用来注册内置的C++模块的。
// node_bindding.cc文件
// Call built-in modules' _register_<module name> function to
// do module registration explicitly.
void RegisterBuiltinModules() {
#define V(modname) _register_##modname();
NODE_BUILTIN_MODULES(V)
#undef V
}
//通过使用宏定义,最终调用下面的方法
// _register_buffer();
// _register_config();
// _register_contextify();
// _register_domain();
// ...
#define NODE_BUILTIN_MODULES(V) \
NODE_BUILTIN_STANDARD_MODULES(V) \
NODE_BUILTIN_OPENSSL_MODULES(V) \
NODE_BUILTIN_ICU_MODULES(V) \
NODE_BUILTIN_REPORT_MODULES(V) \
NODE_BUILTIN_PROFILER_MODULES(V) \
NODE_BUILTIN_DTRACE_MODULES(V)
#define NODE_BUILTIN_STANDARD_MODULES(V) \
V(buffer) \
V(config) \
V(contextify) \
V(domain) \
V(fs) \
V(fs_dir) \
V(fs_event_wrap) \
V(heap_utils) \
V(js_stream) \
V(module_wrap) \
V(native_module) \
V(options) \
V(os) \
V(process_wrap) \
V(process_methods) \
V(symbols) \
V(timers) \
V(util) \
V(uv) \
V(v8) \
#define NODE_BUILTIN_MODULES(V) \
NODE_BUILTIN_STANDARD_MODULES(V) \
NODE_BUILTIN_OPENSSL_MODULES(V) \
NODE_BUILTIN_ICU_MODULES(V) \
NODE_BUILTIN_REPORT_MODULES(V) \
NODE_BUILTIN_PROFILER_MODULES(V) \
NODE_BUILTIN_DTRACE_MODULES(V)
// This is used to load built-in modules. Instead of using
// __attribute__((constructor)), we call the _register_<modname>
// function for each built-in modules explicitly in
// binding::RegisterBuiltinModules(). This is only forward declaration.
// The definitions are in each module's implementation when calling
// the NODE_MODULE_CONTEXT_AWARE_INTERNAL.
#define V(modname) void _register_##modname();
NODE_BUILTIN_MODULES(V)
#undef V
// 声明刚才调用的方法
// _register_buffer();
// _register_config();
// _register_contextify();
// _register_domain();
// ...
上面的代码只是调用方法和声明方法,实际的方法在哪里实现的呢?
发现每个C++内置模块的代码中,最后一句都有下面类似的语句
NODE_MODULE_CONTEXT_AWARE_INTERNAL(buffer, node::Buffer::Initialize)
找到宏定义NODE_MODULE_CONTEXT_AWARE_INTERNAL
// node_binding.h
#define NODE_MODULE_CONTEXT_AWARE_INTERNAL(modname, regfunc) \
NODE_MODULE_CONTEXT_AWARE_CPP(modname, regfunc, nullptr, NM_F_INTERNAL)
#define NODE_MODULE_CONTEXT_AWARE_CPP(modname, regfunc, priv, flags) \
static node::node_module _module = { \
NODE_MODULE_VERSION, \
flags, \
nullptr, \
__FILE__, \
nullptr, \
(node::addon_context_register_func)(regfunc), \
NODE_STRINGIFY(modname), \
priv, \
nullptr}; \
void _register_##modname() { node_module_register(&_module); }
// 定义_module变量,然后创建_register_##modname相关的方法
// Globals per process
static node_module* modlist_internal;
static node_module* modlist_linked;
static thread_local node_module* thread_local_modpending;
// This is set by node::Init() which is used by embedders
bool node_is_initialized = false;
extern "C" void node_module_register(void* m) {
struct node_module* mp = reinterpret_cast<struct node_module*>(m);
if (mp->nm_flags & NM_F_INTERNAL) {
mp->nm_link = modlist_internal;
modlist_internal = mp;
} else if (!node_is_initialized) {
// "Linked" modules are included as part of the node project.
// Like builtins they are registered *before* node::Init runs.
mp->nm_flags = NM_F_LINKED;
mp->nm_link = modlist_linked;
modlist_linked = mp;
} else {
thread_local_modpending = mp;
}
}