我正试图从我的功能的另一个角度调用V8中的回调。所以这段代码注册了回调:
if (args.Length())
{
String::Utf8Value event(args[0]->ToString());
if (event.length())
{
Isolate* isolate = V8Interface::getCurrent()->getIsolate();
Locker locker(isolate);
HandleScope scope(isolate);
callback cb = callback(isolate, Local<Function>::Cast(args[1]));
if(!events.count(*event))
{
events[*event] = callbacks({ cb });
}
else
{
events.find(*event)->second.push_back(cb);
}
}
}
这个人称之为:
void trigger(std::string event)
{
Isolate* isolate = V8Interface::getCurrent()->getIsolate();
Locker locker(isolate);
HandleScope scope(isolate);
if(events.count(event))
{
for(callback cb : events.find(event)->second)
{
Local<Function> local = Local<Function>::New(isolate, cb);
local->Call(isolate->GetCurrentContext()->Global(), 0, {});
}
}
}
可以在我的C ++代码中随时随地调用触发器函数。我尝试了一个简单的例子(init v8然后调用trigger),然后我得到:
#
# Fatal error in C:\OgreSDK\Projects\whitedrop\third_party\io.js\deps\v8\src/api.h, line 386
# CHECK(allow_empty_handle || that != 0) failed
#
这是我的主要内容:
Scribe::V8Interface v8Interface = Scribe::V8Interface();
v8Interface.initialize();
for(Whitedrop::WorldEvent* event : Whitedrop::worldEvents)
{
event->onStart();
}
你可以在这里获得全部资料来源:
https://github.com/whitedrop/whitedrop/tree/feature/v8
第386行是:
/**
* Create a local handle for the content of another handle.
* The referee is kept alive by the local handle even when
* the original handle is destroyed/disposed.
*/
V8_INLINE static Local<T> New(Isolate* isolate, Handle<T> that); // <<<<<<
V8_INLINE static Local<T> New(Isolate* isolate,
const PersistentBase<T>& that);
编辑:我试过,感谢Ben Noordhuis,就像这样:
Isolate* isolate = V8Interface::getCurrent()->getIsolate();
Locker locker(isolate);
HandleScope scope(isolate);
callback cb;
cb.Reset(isolate, Local<Function>::Cast(args[1]));
致电:
Isolate* isolate = V8Interface::getCurrent()->getIsolate();
Locker locker(isolate);
HandleScope scope(isolate);
if(events.count(event))
{
for(callback cb : events.find(event)->second)
{
Local<Function> local = Local<Function>::New(isolate, cb);
local->Call(isolate->GetCurrentContext()->Global(), 0, {});
}
}
但同样的错误:'(
答案 0 :(得分:2)
不确定问题的作者是否还需要答案。无论如何。
继续以前关于将本地处理程序转换为Persistent的答案。
Node.js C ++插件文档页面上有一些示例:
https://nodejs.org/api/addons.html#addons_function_factory
对于持久对象,他们使用静态构造函数方法作为持久性&lt;函数&gt; 。
当模块被包含时,可以通过重置方法初始化构造函数
像这样(实际上我没有在v8文档中找到它的描述 - http://izs.me/v8-docs/classv8_1_1Persistent.html):
// some where in external class or as global var
static Persistent<Function> persistentCallback;
// when need to init
persistentCallback.Reset(isolate, f_tmpl->GetFunction());
要在需要时调用此方法,您应该使用本地句柄转换,如下所示:
Local<Function> f = Local<Function>::New(isoloate,persistentCallback)
请注意,您无法使用句柄指针,因为其 :: New 方法不适合此类参数。
顺便说一句。我发现我不需要在我的代码中使用Persistent处理程序来存储回调方法,以防我已经将它绑定在JS上下文中。在这种情况下,它似乎由GC妥善管理。但是没有其他方法可以在c ++函数调用之间共享变量,例如。当您在模块中存储一些受保护的数据时。
答案 1 :(得分:0)
我认为您应该将Local<T>
投放到Persistent<T>
,然后再将其存入events
。如果您不这样做,v8中的GC可能会随时收集这些功能。
Handle<Function> args0 = Handle<Function>::Cast(args[0]);
Persistent<Function> pfn(args0);
callback cb = callback(isolate, pfn); // use Persistent<T> instead of Local<T>