3

我想在使用 v8 引擎的嵌入式 JavaScript 应用程序中实现此功能。

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(),因为不能保证结果是唯一的。

我也不能只将 Local 存储在中,std::set因为复制构造函数是私有的,并且一旦 removeCallback 或 addCallback 返回它也会被取消作用域。

感谢您提前提供任何帮助。

编辑:我意识到我可以编写一些 javascript 来为我做函数散列,然后调用一个 C++ 绑定函数来迭代所有回调,但我不想每次需要存储 JavaScript 集或散列时都这样做对象。

4

1 回答 1

4

您不能安全地存储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>(这就是我在我的项目中所做的)以获得所需的行为。

于 2014-01-21T20:15:17.143 回答