РЕДАКТИРОВАТЬ: лучший метод, чем голый V8 ниже, должен использовать NanHasInstance
(https://github.com/rvagg/nan#api_nan_has_instance)
In MyObject::Init
:
Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);
tpl->SetClassName(NanNew<String>("MyObject"));
...
NanAssignPersistent(prototype, tpl);
, где prototype
являетсяstatic Persistent<FunctionTemplate>
член MyObject
.
Используйте вот так:
if (NanHasInstance(prototype, handle)) {
MyObject* obj = ObjectWrap::Unwrap<MyObject>(handle);
...
}
С оговоркой, что это мой первый шаг при написании аддона Node, я решил этоТочная проблема, проверяя прототип объекта с моей собственной оберткой вокруг UnWrap
.
Вот патч к демонстрации класса фабрики аддонов, показывающий метод: 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
не изменит способ использования внутренних полей.