Node.js node-addon-api Class

Ref: https://github.com/nodejs/node-addon-api#api

<package>
โ”œโ”€โ”€ binding.gyp
โ”œโ”€โ”€ index.js
โ”œโ”€โ”€ node_modules
โ”‚ โ””โ”€โ”€ node-addon-api
โ”‚ โ””โ”€โ”€ ...
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ package-lock.json
โ”œโ”€โ”€ test
โ”‚ โ””โ”€โ”€ ...
โ”œโ”€โ”€ .clang-format
โ””โ”€โ”€ c_src
โ”œโ”€โ”€ class.cpp
โ”œโ”€โ”€ class.h
โ”œโ”€โ”€ class_wrap.cpp
โ”œโ”€โ”€ class_wrap.h
โ””โ”€โ”€ <target>.cpp

binding.gyp

Ref: https://github.com/nodejs/node-addon-api/blob/master/doc/setup.md

{
"targets": [
{
...
"sources": [
"c_src/Class.cpp",
"c_src/Class.h",
"c_src/ClassWrapper.cpp",
"c_src/ClassWrapper.h",
"c_src/<target>.cpp",
],
...
}
]
}

Wrapper

c_src/Class.h

#pragma once
class Class {
public:
Class(double value);
double get_value(void);
double add(double value);
private:
double m_value;
};

c_src/Class.cpp

#include "Class.h"
Class::Class(double value)
: m_value(value) {}
double Class::get_value(void) { return m_value; }
double Class::add(double value) {
m_value += value;
return m_value;
}

c_src/ClassWrapper.h

InstanceMethod๋กœ ๋“ฑ๋ก ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • typedef void (T::*InstanceVoidMethodCallback)(const CallbackInfo& info);
  • typedef Napi::Value (T::*InstanceMethodCallback)(const CallbackInfo& info);
#pragma once
#include "Class.h"
#include <napi.h>
class ClassWrapper: public Napi::ObjectWrap<ClassWrapper> {
public:
static Napi::Object init(Napi::Env env, Napi::Object exports);
ClassWrapper(const Napi::CallbackInfo &info);
private:
static Napi::FunctionReference m_constructor;
Class * m_Class;
Napi::Value get_value(const Napi::CallbackInfo &info);
Napi::Value add(const Napi::CallbackInfo &info);
};

c_src/ClassWrapper.cpp

#include "ClassWrapper.h"
Napi::FunctionReference ClassWrapper::m_constructor;
Napi::Object ClassWrapper::init(Napi::Env env, Napi::Object exports) {
Napi::HandleScope scope(env);
Napi::Function funcs
= DefineClass(env,
"Class",
{
InstanceMethod("get_value", &ClassWrapper::get_value),
InstanceMethod("add", &ClassWrapper::add),
});
m_constructor = Napi::Persistent(funcs);
m_constructor.SuppressDestruct();
exports.Set("Class", funcs);
return exports;
}
ClassWrapper::ClassWrapper(const Napi::CallbackInfo &info)
: Napi::ObjectWrap<ClassWrapper>(info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
if(info.Length() < 1 || ! info[0].IsNumber()) {
Napi::TypeError::New(env, "Arguments must be (value).")
.ThrowAsJavaScriptException();
}
double value = info[0].As<Napi::Number>();
m_Class = new Class(value);
}
Napi::Value ClassWrapper::get_value(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Number::New(env, m_Class->get_value());
}
Napi::Value ClassWrapper::add(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
if(info.Length() < 1 || ! info[0].IsNumber()) {
Napi::TypeError::New(env, "Arguments must be (value).")
.ThrowAsJavaScriptException();
}
double value = info[0].As<Napi::Number>();
return Napi::Number::New(env, m_Class->add(value));
}

c_src/<target>.cpp

#include "ClassWrapper.h"
#include <napi.h>
Napi::Object init_all(Napi::Env env, Napi::Object exports) {
return ClassWrapper::init(env, exports);
}
NODE_API_MODULE(NODE_GYP_MODULE_NAME, init_all)

Build

npm run build

test/test.js

const addon = require("../build/Release/<target>");
console.log("wrapper info", addon);
const testClass = new addon.Class(10);
console.log(testClass.get_value());
console.log(testClass.add(2));
node test/test.js
wrapper info { Class: [Function: Class] }
10
12
Last updated on