[英]How to call a javascript callback from C++
我试图从我的函数的另一个点调用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, {});
}
}
但同样的错误:'(
不确定问题的作者是否还需要答案。 无论如何。
继续以前关于将本地处理程序转换为Persistent的答案。 Node.js C ++插件文档页面上有一些示例:
https://nodejs.org/api/addons.html#addons_function_factory
对于持久对象,它们使用静态构造函数方法作为Persistent <Function> 。 当模块被包含时,构造函数可以通过Reset方法初始化(实际上我没有在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)
请注意,您不能使用Handle指针,因为它的:: New方法不适合此类参数。
BTW。 我发现我不需要在我的代码中使用Persistent处理程序来存储回调方法,以防我已经将它绑定在JS上下文中。 在这种情况下,它似乎由GC妥善管理。 但是没有其他方法可以在c ++函数调用之间共享变量,例如。 当您在模块中存储一些受保护的数据时。
我认为你应该将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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.