Хранение дескрипторов объектов в hashmap или в движке Google V8

Я хотел бы реализовать эту функциональность во встроенном приложении JavaScript, которое использует движок v8.

function myFunction1() {
   //do stuff
}

function myFunction2() {
   //do other stuff
}

myAddon.addCallback(myFunction1);
myAddon.addCallback(myFunction2);
myAddon.removeCallback(myFunction1);

Для этого мне нужно сохранить эти функции в std::set вот так

void addCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   v8::HandleScope scope(args.GetIsolate());
   v8::Local<v8::Function> cb = v8::Local<v8::Function>::Cast(args[0]);
   std::set mySet = this->mySet;
   //now how do I insert a reference to this function into mySet so I can retrieve
   //it later
}

void removeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
   v8::HandleScope scope(args.GetIsolate());
   v8::Local<v8::Function> cb = v8::Local<v8::Function>::Cast(args[0]);
   std::set mySet = this->mySet;
   //now how do I remove the element in this set that refers to this function?
}

Как можно это сделать? Я не хочу использовать v8::Object::GetIdentityHash() потому что результат не гарантированно будет уникальным.

Я также не могу просто хранить местное в std::set потому что конструктор копирования является закрытым, и он также будет удален после возврата removeCallback или addCallback.

Спасибо за любую помощь заранее.

Редактировать: я понимаю, что мог бы написать некоторый javascript для хеширования функции, а затем вызвать одну функцию, связанную с C++, для итерации по всем обратным вызовам, но я бы не стал делать это каждый раз, когда мне нужно хранить наборы или хэши JavaScript объекты.

1 ответ

Это правильно, что вы не можете безопасно хранить Local<T> обрабатывать, потому что, когда он выходит из области видимости, ваш функциональный объект может стать доступным для сборки мусора. Что вам нужно, так это постоянная ручка. Вы можете построить его из местных как:

v8::Local<v8::Function> cb = v8::Local<v8::Function>::Cast(args[0]);
v8::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function>> value(isolate, cb);

Заметка CopyablePersistentTraits что позволяет обрабатывать копирование. Существует также NonCopyablePersistentTraits если вы хотели бы предотвратить это.

Теперь вы можете поместить его в вектор:

std::vector<v8::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function>>> v;
v.push_back(value);

Преобразовать обратно в местное:

v8::Local<v8::Function> local = v8::Local<v8::Function>::New(isolate, value);

За std::set Вы также должны предоставить функцию сравнения для элементов. Это также может быть хорошей идеей, чтобы обернуть v8::Persistent<T> в свой собственный класс, как PersistentWrapper<T> (это то, что я делаю в своем проекте), чтобы получить желаемое поведение.

Другие вопросы по тегам