是否可以使用私有 js 构造函数在 node-addon-api 中创建一个 ObjectWrap,并且只能在 C++ 中实例化?
Is it possible to create an ObjectWrap in node-addon-api with a private js constructor and that can be instantiated in c++ only?
我目前正在使用 node-addon-api (Napi)
在 C++ 中编写一个 node.js 插件。从我在不同的文档和教程中看到的,每个对象都必须扩展 Napi::ObjectWrap
才能被视为 js 对象。然后在js中调用构造函数就可以了。
但是,如果我希望这个特定对象仅由另一个对象提供并将 js 构造函数设为私有怎么办?
考虑这个案例
class Provided: public Napi::ObjectWrap<Provided> {
public:
// Init function for exports
static Init(Napi::Env, Napi::Object exports);
// what if I want my constructor to have a value instead of a CallbackInfo and only allow instantiation from c++ ?
Provided(std::string value);
private:
std::string m_value;
};
class MyProvider: public Napi::ObjectWrap<MyProvider> {
public:
// Init function for exports
static Init(Napi::Env, Napi::Object exports) {
Napi::Function func = DefineClass(env, "provider", {InstanceMethod("getProvided", &MyProvider::GetProvided)});
constructor = Napi::Persistent(func);
constructor.SupressDestruct();
exports.Set("Provider", func);
return exports;
}
MyProvider(Napi::CallbackInfo const&): Napi::ObjectWrap<MyProvider>(info) {
this->m_provided = Provided("my value");
}
private:
Provided m_provided;
static Napi::FunctionReference constructor;
}
如何在提供的构造函数中不包含Napi::CallbackInfo
我的解决方案是使用 DefineClass
的 data
参数来传递我的参数(在我的例子中只有一个,但我想你可以传递一个 array/vector/whatever 容器如你所愿)。然后我创建了一个“Provided”class 的实例并返回了它。但是一个例子比我的解释更有价值:
class Provided: public Napi::ObjectWrap<Provided> {
public:
// Factory for a JavaScript class instance
static Create(Napi::Env env, std::string &myString) {
// Pass the argument(s) as last DefineClass argument
Napi::Function func = DefineClass(env, "provided", {InstanceMethod("getString", &MyProvider::GetString)}, &myString);
};
Provided(const Napi::CallbackInfo &info) {
// And get the c++ object back in the constructor.
// It requires a cast as it goes through being a void pointer.
myValue = *(std::string *)info.Data();
};
private:
std::string myValue;
Napi::Value GetString(const Napi::CallbackInfo &info) {
return Napi::String::New(info.Env(), myValue);
};
};
class MyProvider: public Napi::ObjectWrap<MyProvider> {
public:
// Init function for exports
static Init(Napi::Env env, Napi::Object exports) {
Napi::Function func = DefineClass(env, "provider", {InstanceMethod("getProvided", &MyProvider::GetProvided)});
constructor = Napi::Persistent(func);
constructor.SupressDestruct();
exports.Set("Provider", func);
return exports;
}
MyProvider(Napi::CallbackInfo const&): Napi::ObjectWrap<MyProvider>(info) {
// Use the "Factory" to create an object instance.
m_provided = Provided::Create(info.Env(), "my value");
}
private:
Provided m_provided;
static Napi::FunctionReference constructor;
}
我目前正在使用 node-addon-api (Napi)
在 C++ 中编写一个 node.js 插件。从我在不同的文档和教程中看到的,每个对象都必须扩展 Napi::ObjectWrap
才能被视为 js 对象。然后在js中调用构造函数就可以了。
但是,如果我希望这个特定对象仅由另一个对象提供并将 js 构造函数设为私有怎么办?
考虑这个案例
class Provided: public Napi::ObjectWrap<Provided> {
public:
// Init function for exports
static Init(Napi::Env, Napi::Object exports);
// what if I want my constructor to have a value instead of a CallbackInfo and only allow instantiation from c++ ?
Provided(std::string value);
private:
std::string m_value;
};
class MyProvider: public Napi::ObjectWrap<MyProvider> {
public:
// Init function for exports
static Init(Napi::Env, Napi::Object exports) {
Napi::Function func = DefineClass(env, "provider", {InstanceMethod("getProvided", &MyProvider::GetProvided)});
constructor = Napi::Persistent(func);
constructor.SupressDestruct();
exports.Set("Provider", func);
return exports;
}
MyProvider(Napi::CallbackInfo const&): Napi::ObjectWrap<MyProvider>(info) {
this->m_provided = Provided("my value");
}
private:
Provided m_provided;
static Napi::FunctionReference constructor;
}
如何在提供的构造函数中不包含Napi::CallbackInfo
我的解决方案是使用 DefineClass
的 data
参数来传递我的参数(在我的例子中只有一个,但我想你可以传递一个 array/vector/whatever 容器如你所愿)。然后我创建了一个“Provided”class 的实例并返回了它。但是一个例子比我的解释更有价值:
class Provided: public Napi::ObjectWrap<Provided> {
public:
// Factory for a JavaScript class instance
static Create(Napi::Env env, std::string &myString) {
// Pass the argument(s) as last DefineClass argument
Napi::Function func = DefineClass(env, "provided", {InstanceMethod("getString", &MyProvider::GetString)}, &myString);
};
Provided(const Napi::CallbackInfo &info) {
// And get the c++ object back in the constructor.
// It requires a cast as it goes through being a void pointer.
myValue = *(std::string *)info.Data();
};
private:
std::string myValue;
Napi::Value GetString(const Napi::CallbackInfo &info) {
return Napi::String::New(info.Env(), myValue);
};
};
class MyProvider: public Napi::ObjectWrap<MyProvider> {
public:
// Init function for exports
static Init(Napi::Env env, Napi::Object exports) {
Napi::Function func = DefineClass(env, "provider", {InstanceMethod("getProvided", &MyProvider::GetProvided)});
constructor = Napi::Persistent(func);
constructor.SupressDestruct();
exports.Set("Provider", func);
return exports;
}
MyProvider(Napi::CallbackInfo const&): Napi::ObjectWrap<MyProvider>(info) {
// Use the "Factory" to create an object instance.
m_provided = Provided::Create(info.Env(), "my value");
}
private:
Provided m_provided;
static Napi::FunctionReference constructor;
}