我将2个C ++类公开为javascript类VanillaOption
和NoomraEngine
,两者都继承自ObjectWrap
。
在NoomraEngine
中的以下方法中,我应该收到之前“已包装”的VanillaOption
:
Handle<Value>
NoomraEngine::Price(const Arguments& args) {
HandleScope scope;
Local<Object> object = args[0]->ToObject(); // VanillaOption expected in args[0]
VanillaOption* equityOption = ObjectWrap::Unwrap<VanillaOption>(object);
Local<Number> x = Number::New(this->price(equityOption));
return scope.Close(x);
}
一切正常,但如果我将错误的类型传递给方法,节点会在ObjectWrap::Unwrap
中崩溃。
我的问题是如何确保我在args[0]
收到了正确的类型?
答案 0 :(得分:3)
编辑:比下面的V8更好的方法是使用NanHasInstance
(https://github.com/rvagg/nan#api_nan_has_instance)
在MyObject::Init
:
Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);
tpl->SetClassName(NanNew<String>("MyObject"));
...
NanAssignPersistent(prototype, tpl);
其中prototype
是Persistent<FunctionTemplate>
的静态MyObject
成员。
像这样使用:
if (NanHasInstance(prototype, handle)) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(handle);
...
}
有一点需要注意,这是我第一次编写Node插件,我通过UnWrap
周围的自己的包装器检查对象的原型来解决这个问题。
以下是addon工厂类演示的补丁,显示了该方法: https://github.com/petli/node-addon-examples/commit/d3e92cd060a26da2623690718e78f9005db060a8
它只支持工厂生成的对象,而不支持暴露构造函数的对象,以便用户可以从基类继承。然而,这可以通过走原型链来推广。
总之,它抓住了MyObject::Init
中对预期类原型的引用:
Local<Object> obj = constructor->NewInstance();
prototype = Persistent<Value>::New(obj->GetPrototype());
然后在解除引用对象之前检查:
MyObject* MyObject::CheckedUnWrap(Handle<Object> handle)
{
if (!handle.IsEmpty() && handle->InternalFieldCount() == 1) {
Handle<Value> objproto = handle->GetPrototype();
if (objproto == prototype) {
// OK, this is us
return ObjectWrap::Unwrap<MyObject>(handle);
}
}
ThrowException(Exception::TypeError(String::New("<this> is not a MyObject")));
return NULL;
}
然后所有功能都使用CheckedUnWrap
代替:
Handle<Value> MyObject::PlusOne(const Arguments& args) {
HandleScope scope;
MyObject* obj = CheckedUnWrap(args.This());
if (obj) {
obj->counter_ += 1;
return scope.Close(Number::New(obj->counter_));
}
else {
// Invalid type, an exception has been thrown so return an empty value
return Handle<Value>();
}
}
我还在考虑添加一个内部字段并将其设置为一些魔术指针,但是代码依赖于node::ObjectWrap
不会改变它使用内部字段的方式。
答案 1 :(得分:3)
更新:由于已弃用NanHasInstance
,因此此答案的新解决方案是使用bool FunctionTemplate::HasInstance(Local<Value> object)
。如果给定对象是此函数模板的实例,则此函数返回true。
Persistent<Function> Wrapper::constructor;
Persistent<FunctionTemplate> Wrapper::tpl;
然后在Wrapper::Init()
函数中,设置公共Persistent对象:
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New);
// ...
Wrapper::tpl.Reset(isolate, tpl);
现在打开包装:
Local<FunctionTemplate> wrapper_tpl = Wrapper::tpl.Get(isolate);
if (!(wrapper_tpl->HasInstance(args[0]))) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "Argument must be a Wrapper object")));
return;
}
// Now we are safe to call ObjectWrap::Unwrap
答案 2 :(得分:-1)
节点::缓冲:: HasInstance(参数[0]);
另见: http://www.lamedoc.com/node.js/classnode_1_1Buffer.html#a4cc6fa734527df461641c6e93e6d1197