当调用ObjectWrap :: Unwrap在一个Nodejs加载项时如何检查正确的types?

我有2个C ++类公开为JavaScript类, VanillaOptionNoomraEngine ,都从ObjectWrapinheritance。

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); } 

一切工作正常,但如果我传递错误的types的方法,节点崩溃在ObjectWrap::Unwrap

我的问题是我如何确保我已经收到args[0]正确的types?

编辑:比下面的裸V8更好的方法是使用NanHasInstancehttps://github.com/rvagg/nan#api_nan_has_instance

MyObject::Init

 Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New); tpl->SetClassName(NanNew<String>("MyObject")); ... NanAssignPersistent(prototype, tpl); 

其中prototypeMyObject的静态Persistent<FunctionTemplate>成员。

像这样使用:

 if (NanHasInstance(prototype, handle)) { MyObject* obj = ObjectWrap::Unwrap<MyObject>(handle); ... } 

有一点需要注意的是,这是我第一次编写一个Node插件,我用自己的UnWrap封装来检查对象的原型,从而解决了这个问题。

下面是插件工厂类演示的补丁,显示了该方法: https : //github.com/petli/node-addon-examples/commit/d3e92cd060a26da2623690718e78f9005db060a8

它只支持工厂生成的对象,而不支持公开构造函数的对象,以便用户可以inheritance基类。 但是,这可以通过走原型链来推广。

总之,它抓住在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不会改变它如何使用内部字段。

更新 :因为NanHasInstance已被弃用,这个答案的新解决scheme是使用bool FunctionTemplate::HasInstance(Local<Value> object) 。 如果给定对象是此函数模板的一个实例,则此函数返回true。

 Persistent<Function> Wrapper::constructor; Persistent<FunctionTemplate> Wrapper::tpl; 

然后在你的Wrapper::Init()函数中,设置public 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 

节点::缓冲:: HasInstance(参数[0]);

另见: http : //www.lamedoc.com/node.js/classnode_1_1Buffer.html#a4cc6fa734527df461641c6e93e6d1197