在Nodejs插件中调用ObjectWrap :: Unwrap时如何检查正确的类型?

Big*_*ion 8 add-on node.js

我有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);
}
Run Code Online (Sandbox Code Playgroud)

一切正常,但如果我将错误的类型传递给方法,节点崩溃了ObjectWrap::Unwrap.

我的问题是如何确保我收到了正确的类型args[0]

Pet*_*erg 3

编辑:比下面的裸 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);
Run Code Online (Sandbox Code Playgroud)

其中prototype是 的静态Persistent<FunctionTemplate>成员MyObject

像这样使用:

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

需要注意的是,这是我第一次编写 Node 插件,我通过使用我自己的包装器检查对象的原型解决了这个问题UnWrap

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

它仅支持工厂生成的对象,而不支持公开构造函数以便用户可以从基类继承的对象。然而,这可以通过遍历原型链来推广。

总之,它抓住了对预期类原型的引用MyObject::Init

Local<Object> obj = constructor->NewInstance();
prototype = Persistent<Value>::New(obj->GetPrototype());
Run Code Online (Sandbox Code Playgroud)

然后在取消引用对象之前检查:

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;
}
Run Code Online (Sandbox Code Playgroud)

然后所有函数都使用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>();
  }
}
Run Code Online (Sandbox Code Playgroud)

我还考虑添加一个内部字段并将其设置为一些魔术指针,但是代码将依赖于它不会node::ObjectWrap改变它使用内部字段的方式。