Given Zig's promise of C header includes, it would be cool for the docs or blog to have an example of writing a "Hello Node.js" native addon for Node.js using N-API and Zig.
Node's N-API is fairly recent, and many existing native addons for Node written using Nan etc. are probably being ported. Now might be a great time for some of these native Node modules to consider using Zig instead of C/C++.
It seems like n-api requires that modules register themselves from constructors that run when their dll is opened. If you don't then node's process.dlopen fails with:
Error: Module did not self-register.
This issue will require a way to register a dynamic library constructor.
The code I was playing with:
// https://nodejs.org/api/n-api.html
const std = @import("std");
const napi = @cImport({
@cInclude("node_api.h");
});
fn NAPI_MODULE_X(modname: []const u8, regfunc: napi.napi_addon_register_func, priv: ?*c_void, flags: c_uint) void {
napi_module_register(&napi_module {
.nm_version = napi.NAPI_MODULE_VERSION,
.nm_flags = flags,
.nm_filename = null,
.nm_register_func = regfunc,
.nm_modname = modname,
.nm_priv = priv,
.reserved = c_void(null) ** 4,
});
}
fn NAPI_MODULE(modname: []const u8, regfunc: napi.napi_addon_register_func) void {
return NAPI_MODULE_X(modname, regfunc, null, 0);
}
extern fn myfunc(env: napi.napi_env, exports: napi.napi_value) napi.napi_value {
var answer: napi.napi_value = undefined;
var status: napi.napi_status = undefined;
status = napi.napi_create_int64(env, 42, &answer);
if (status != .napi_ok) return null;
status = napi.napi_set_named_property(env, exports, &"answer", answer);
if (status != .napi_ok) return null;
return exports;
}
comptime {
@export("napi_register_module_v1", myfunc, .Strong);
}
zig build-lib -dynamic --library c -isystem /usr/include/node/ n-api.zig
I have managed to do exactly that thanks to the help of the nice zig people in freenode by doing that on linux:
export const init_array linksection(".init_array") = [_]extern fn () void {
myFunc
};
@andrewrk this issue is a good example use case for why we need the ability to support constructors. The workaround found is linux and elf specific.
Most helpful comment
@andrewrk this issue is a good example use case for why we need the ability to support constructors. The workaround found is linux and elf specific.