The other day I accidentally did this:
NODE_MODULES("hello", init)
It doesn't compile. Not noticing my mistake I changed it to this:
NODE_MODULES(init, "hello")
That compiles just fine but node crashes hard (SIGSEGV) when loading the add-on. That is because the second argument is casted relentlessly to a function pointer by the macro. I wondered why. Turns out that the cast serves as poor man's overloaded function in C. That is, the add-on's init function is allowed to take fewer arguments than the caller (nodes dlopen) provides. However, this "feature" means that the init functions type doesn't match. Hence the cast. The cast breaks type safety completely and results in the miscompilation and crash described above.
Another thing I've been wondering about is the name argument. It seems a little kafkaesque that I have to state the name of the target add-on in the add-on, just so node can check that the add-on's name is in fact the add-on's name. Specially since the build system already knows the name of the target and all that is needed is:
'target_defaults': { 'defines': ['NODE_MODULE_NAME=>(_target_name)'] }
in node-gyp's addon.gypi. Boom. All add-on's know their name and we can drop the argument.
Here is what I'd like to write:
NODE_MODULE(v8::Handle<v8::Object> exports/*, maybe more */) {
exports->Set(...);
}
It is more compact, very readable and just leaves less room for error... provided that type safety is restored.
Thoughts?