从 NodeJS Addon 构造本机对象
Constructing native object from NodeJS Addon
预期
我想使用像下面的 javascript 模块一样工作的本机 NodeJS 模块来实现
class C1{
make(){return new C2()}
}
class C2{}
module.exports({C1, C2})
方法
我的尝试是,(在其他一些失败的尝试中)
// so.cpp
#include <napi.h>
class C1: public Napi::ObjectWrap<C1> {
public:
C1(const Napi::CallbackInfo &info);
static void Initialize(Napi::Env& env, Napi::Object& target);
Napi::Value make(const Napi::CallbackInfo &info);
};
class C2: public Napi::ObjectWrap<C2> {
static Napi::Function constructor;
public:
C2(const Napi::CallbackInfo &info);
static void Initialize(Napi::Env& env, Napi::Object& target);
static C2 *New(const std::initializer_list<napi_value>& args);
};
Napi::Function C2::constructor;
void C2::Initialize(Napi::Env& env, Napi::Object& target){
constructor = Napi::ObjectWrap<C2>::DefineClass(env, "C2", {});
target.Set("C2", constructor);
}
void C1::Initialize(Napi::Env& env, Napi::Object& target) {
Napi::Function constructor = Napi::ObjectWrap<C1>::DefineClass(env, "C1", {
Napi::ObjectWrap<C1>::InstanceMethod("make", &C1::make),
});
target.Set("C1", constructor);
}
C2 *C2::New(const std::initializer_list<napi_value>& args){
return Napi::ObjectWrap<C2>::Unwrap(constructor.New(args));
}
C2::C2(const Napi::CallbackInfo &info): Napi::ObjectWrap<C2>(info) {}
C1::C1(const Napi::CallbackInfo &info): Napi::ObjectWrap<C1>(info) {}
// make() {return new C2()}
Napi::Value C1::make(const Napi::CallbackInfo &info){
C2 *jsclat = C2::New({});
return jsclat->Value();
}
// module.exports = {C1, C2}
Napi::Object Init(Napi::Env env, Napi::Object exports)
{
C1::Initialize(env, exports);
C2::Initialize(env, exports);
return exports;
}
NODE_API_MODULE(so, Init);
问题
当我尝试使用来自 javascript 的已编译模块时,节点已终止
const m = require('bindings')('hello')
const c1 = new m.c1()
c1.make() // FATAL ERROR: Error::New napi_get_last_error_info
// Aborted
环境
如果你想要和我一样的环境,这里有一个dockerfile。
FROM node:13.8.0-alpine3.11
RUN apk add --upgrade git python3 g++ make
WORKDIR /opt
RUN git clone https://github.com/nodejs/node-addon-examples.git
WORKDIR /opt/node-addon-examples/1_hello_world/node-addon-api/
RUN npm install \
&& npm install --save-dev gyp
&& npx node-gyp configure
COPY so.cpp hello.cc
RUN npx node-gyp rebuild
您不能在创建它的函数之外使用 constructor
- 它是在堆栈上分配的自动 v8::Local
引用 - 您需要一个持久引用来执行此操作:
#include <napi.h>
class C1: public Napi::ObjectWrap<C1> {
public:
C1(const Napi::CallbackInfo &info);
static void Initialize(Napi::Env &env, Napi::Object &target);
Napi::Value make(const Napi::CallbackInfo &info);
};
class C2: public Napi::ObjectWrap<C2> {
static Napi::Function constructor;
public:
static Napi::FunctionReference *New;
C2(const Napi::CallbackInfo &info);
static void Initialize(Napi::Env& env, Napi::Object& target);
};
Napi::FunctionReference *C2::New;
void C2::Initialize(Napi::Env& env, Napi::Object& target){
Napi::Function constructor = Napi::ObjectWrap<C2>::DefineClass(env, "C2", {});
target.Set("C2", constructor);
New = new Napi::FunctionReference();
*New = Napi::Persistent(constructor);
}
void C1::Initialize(Napi::Env& env, Napi::Object& target) {
Napi::Function constructor = Napi::ObjectWrap<C1>::DefineClass(env, "C1", {
Napi::ObjectWrap<C1>::InstanceMethod("make", &C1::make),
});
target.Set("C1", constructor);
}
C2::C2(const Napi::CallbackInfo &info): Napi::ObjectWrap<C2>(info) {}
C1::C1(const Napi::CallbackInfo &info): Napi::ObjectWrap<C1>(info) {}
// make() {return new C2()}
Napi::Value C1::make(const Napi::CallbackInfo &info){
Napi::Value c2 = C2::New->New({});
return c2;
}
// module.exports = {C1, C2}
Napi::Object Init(Napi::Env env, Napi::Object exports)
{
C1::Initialize(env, exports);
C2::Initialize(env, exports);
return exports;
}
NODE_API_MODULE(so, Init);
预期
我想使用像下面的 javascript 模块一样工作的本机 NodeJS 模块来实现
class C1{
make(){return new C2()}
}
class C2{}
module.exports({C1, C2})
方法
我的尝试是,(在其他一些失败的尝试中)
// so.cpp
#include <napi.h>
class C1: public Napi::ObjectWrap<C1> {
public:
C1(const Napi::CallbackInfo &info);
static void Initialize(Napi::Env& env, Napi::Object& target);
Napi::Value make(const Napi::CallbackInfo &info);
};
class C2: public Napi::ObjectWrap<C2> {
static Napi::Function constructor;
public:
C2(const Napi::CallbackInfo &info);
static void Initialize(Napi::Env& env, Napi::Object& target);
static C2 *New(const std::initializer_list<napi_value>& args);
};
Napi::Function C2::constructor;
void C2::Initialize(Napi::Env& env, Napi::Object& target){
constructor = Napi::ObjectWrap<C2>::DefineClass(env, "C2", {});
target.Set("C2", constructor);
}
void C1::Initialize(Napi::Env& env, Napi::Object& target) {
Napi::Function constructor = Napi::ObjectWrap<C1>::DefineClass(env, "C1", {
Napi::ObjectWrap<C1>::InstanceMethod("make", &C1::make),
});
target.Set("C1", constructor);
}
C2 *C2::New(const std::initializer_list<napi_value>& args){
return Napi::ObjectWrap<C2>::Unwrap(constructor.New(args));
}
C2::C2(const Napi::CallbackInfo &info): Napi::ObjectWrap<C2>(info) {}
C1::C1(const Napi::CallbackInfo &info): Napi::ObjectWrap<C1>(info) {}
// make() {return new C2()}
Napi::Value C1::make(const Napi::CallbackInfo &info){
C2 *jsclat = C2::New({});
return jsclat->Value();
}
// module.exports = {C1, C2}
Napi::Object Init(Napi::Env env, Napi::Object exports)
{
C1::Initialize(env, exports);
C2::Initialize(env, exports);
return exports;
}
NODE_API_MODULE(so, Init);
问题
当我尝试使用来自 javascript 的已编译模块时,节点已终止
const m = require('bindings')('hello')
const c1 = new m.c1()
c1.make() // FATAL ERROR: Error::New napi_get_last_error_info
// Aborted
环境
如果你想要和我一样的环境,这里有一个dockerfile。
FROM node:13.8.0-alpine3.11
RUN apk add --upgrade git python3 g++ make
WORKDIR /opt
RUN git clone https://github.com/nodejs/node-addon-examples.git
WORKDIR /opt/node-addon-examples/1_hello_world/node-addon-api/
RUN npm install \
&& npm install --save-dev gyp
&& npx node-gyp configure
COPY so.cpp hello.cc
RUN npx node-gyp rebuild
您不能在创建它的函数之外使用 constructor
- 它是在堆栈上分配的自动 v8::Local
引用 - 您需要一个持久引用来执行此操作:
#include <napi.h>
class C1: public Napi::ObjectWrap<C1> {
public:
C1(const Napi::CallbackInfo &info);
static void Initialize(Napi::Env &env, Napi::Object &target);
Napi::Value make(const Napi::CallbackInfo &info);
};
class C2: public Napi::ObjectWrap<C2> {
static Napi::Function constructor;
public:
static Napi::FunctionReference *New;
C2(const Napi::CallbackInfo &info);
static void Initialize(Napi::Env& env, Napi::Object& target);
};
Napi::FunctionReference *C2::New;
void C2::Initialize(Napi::Env& env, Napi::Object& target){
Napi::Function constructor = Napi::ObjectWrap<C2>::DefineClass(env, "C2", {});
target.Set("C2", constructor);
New = new Napi::FunctionReference();
*New = Napi::Persistent(constructor);
}
void C1::Initialize(Napi::Env& env, Napi::Object& target) {
Napi::Function constructor = Napi::ObjectWrap<C1>::DefineClass(env, "C1", {
Napi::ObjectWrap<C1>::InstanceMethod("make", &C1::make),
});
target.Set("C1", constructor);
}
C2::C2(const Napi::CallbackInfo &info): Napi::ObjectWrap<C2>(info) {}
C1::C1(const Napi::CallbackInfo &info): Napi::ObjectWrap<C1>(info) {}
// make() {return new C2()}
Napi::Value C1::make(const Napi::CallbackInfo &info){
Napi::Value c2 = C2::New->New({});
return c2;
}
// module.exports = {C1, C2}
Napi::Object Init(Napi::Env env, Napi::Object exports)
{
C1::Initialize(env, exports);
C2::Initialize(env, exports);
return exports;
}
NODE_API_MODULE(so, Init);