Node.js addon 을 개발하는 방법
Node.js 에서 addon 을 개발하는 방법
1. napi
기존 v8, libuv, nan 을 사용해 개발한 addon 모듈은 API/ABI 안정성이 보장되지 못하고 Node.js 주요 릴리즈마다 재컴파일 해야한다.
napi 는 v8 같은 js 런타임에 독립적이고 API/ABI 안정성이 보장된다. 그리고 Node.js 버전마다 재컴파일 하지 않아도 된다.
#include <assert.h>
#include <node_api.h>
static napi_value Method(napi_env env, napi_callback_info info) {
napi_status status;
napi_value world;
status = napi_create_string_utf8(env, "world", 5, &world);
assert(status == napi_ok);
return world;
}
#define DECLARE_NAPI_METHOD(name, func)
{ name, 0, func, 0, 0, 0, napi_default, 0 }
static napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_property_descriptor desc = DECLARE_NAPI_METHOD("hello", Method);
status = napi_define_properties(env, exports, 1, &desc);
assert(status == napi_ok);
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
+ node-addon-api 모듈
#include <napi.h>
Napi::String Method(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
return Napi::String::New(env, "world");
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set(Napi::String::New(env, "hello"), Napi::Function::New(env, Method));
return exports;
}
NODE_API_MODULE(hello, Init)
napi 활용을 단순화 하는 헤더 전용 래퍼 클래스
2. v8, libuv 라이브러리
// hello.cc
#include <node.h>
namespace demo {
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();
args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world").ToLocalChecked());
}
void Initialize(Local<Object> exports) {
NODE_SET_METHOD(exports, "hello", Method);
}
NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
}
3. nan
Native abstractions for Node, 옛날에 사용하던 방법
#include <nan.h>
void Method(const Nan::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(Nan::New("world").ToLocalChecked());
}
void Init(v8::Local<v8::Object> exports) {
v8::Local<v8::Context> context = exports->CreationContext();
exports->Set(context,
Nan::New("hello").ToLocalChecked(), Nan::New<v8::FunctionTemplate>(Method) ->GetFunction(context) .ToLocalChecked());
}
NODE_MODULE(hello, Init);