Я новичок в дополнениях nodejs и на лету учусь работать с существующим кодом. У меня есть ситуация, когда я не понимаю, как вызывается конкретный конструктор C ++, и как устанавливается значение аргумента.
Есть два чистых конструктора C ++:
Nan::Persistent<v8::Function> Event::constructor;
// Construct a blank event from the context metadata
Event::Event() {
oboe_event_init(&event, oboe_context_get());
}
// Construct a new event and point an edge at another
Event::Event(const oboe_metadata_t *md, bool addEdge) {
// both methods copy metadata (version, task_id, flags) from
// md to this->event and create a new random op_id.
if (addEdge) {
// create_event automatically adds edge in event to md
// (so event points an edge to the op_id in md).
oboe_metadata_create_event(md, &event);
} else {
// initializes new Event with md's task_id & new random op_id;
// no edges set
oboe_event_init(&event, md);
}
}
// Remember to cleanup the struct when garbage collected
Event::~Event() {
oboe_event_destroy(&event);
}
Есть три NewInstance
объявления: один с двумя аргументами, один с одним и один без.
v8::Local<v8::Object> Event::NewInstance(Metadata* md, bool addEdge) {
Nan::EscapableHandleScope scope;
const unsigned argc = 2;
v8::Local<v8::Value> argv[argc] = {
Nan::New<v8::External>(md),
Nan::New(addEdge)
};
v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
v8::Local<v8::Object> instance = cons->NewInstance(argc, argv);
return scope.Escape(instance);
}
v8::Local<v8::Object> Event::NewInstance(Metadata* md) {
Nan::EscapableHandleScope scope;
const unsigned argc = 1;
v8::Local<v8::Value> argv[argc] = { Nan::New<v8::External>(md) };
v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
v8::Local<v8::Object> instance = cons->NewInstance(argc, argv);
return scope.Escape(instance);
}
v8::Local<v8::Object> Event::NewInstance() {
Nan::EscapableHandleScope scope;
const unsigned argc = 0;
v8::Local<v8::Value> argv[argc] = {};
v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
v8::Local<v8::Object> instance = cons->NewInstance(argc, argv);
return scope.Escape(instance);
}
И есть код инициализации модуля, который выполняет немного магии, чтобы создать шаблон функции конструктора:
// Wrap the C++ object so V8 can understand it
void Event::Init(v8::Local<v8::Object> exports) {
Nan::HandleScope scope;
// Prepare constructor template
v8::Local<v8::FunctionTemplate> ctor = Nan::New<v8::FunctionTemplate>(New);
ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(Nan::New("Event").ToLocalChecked());
// Statics
Nan::SetMethod(ctor, "startTrace", Event::startTrace);
// Prototype
Nan::SetPrototypeMethod(ctor, "addInfo", Event::addInfo);
Nan::SetPrototypeMethod(ctor, "addEdge", Event::addEdge);
Nan::SetPrototypeMethod(ctor, "getMetadata", Event::getMetadata);
Nan::SetPrototypeMethod(ctor, "toString", Event::toString);
constructor.Reset(ctor->GetFunction());
Nan::Set(exports, Nan::New("Event").ToLocalChecked(), ctor->GetFunction());
}
Наконец, есть код, который вызывает Event::NewInstance
:
Metadata* md = new Metadata(oboe_context_get());
info.GetReturnValue().Set(Event::NewInstance(md));
Через вход в систему я вижу, что NewInstance(md)
вызов заканчивается вызовом аргумента конструктора C ++ с двумя аргументами Event::Event(const oboe_metadata_t *md, bool addEdge)
и что логическое, addEdge
правда.
Как работает один аргумент NewInstance
вызов в конечном итоге вызывает двух аргумент конструктора и как addEdge
получить значение true?
Я не понимаю, как три варианта v8::Local<v8::Object> Event::NewInstance()
объявления отображаются в конструкторе C ++, но кажется, что это должно быть в строке v8::Local<v8::FunctionTemplate> ctor = Nan::New<v8::FunctionTemplate>(New);
Любая помощь будет оценена.
Вот отсутствующий код, показывающий функцию «New», которую я пропустил, потому что в комментарии сказано, что он создает новый экземпляр JavaScript. Но это явно недостающий кусок.
// Creates a new Javascript instance
NAN_METHOD(Event::New) {
if (!info.IsConstructCall()) {
return Nan::ThrowError("Event() must be called as a constructor");
}
Event* event;
if (info.Length() > 0 && info[0]->IsExternal()) {
Metadata* md = static_cast<Metadata*>(info[0].As<v8::External>()->Value());
oboe_metadata_t* context = &md->metadata;
bool addEdge = true;
if (info.Length() == 2 && info[1]->IsBoolean()) {
addEdge = info[1]->BooleanValue();
}
event = new Event(context, addEdge);
} else {
event = new Event();
}
event->Wrap(info.This());
info.GetReturnValue().Set(info.This());
}
Задача ещё не решена.
Других решений пока нет …