如何从C ++调用JavaScriptcallback
我试图从我的函数的另一个angular度调用V8中的callback。 所以这段代码注册callback:
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然后调用触发器),我得到:
# # 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, {}); } }
但同样的错误:'(
不确定问题的作者仍然需要答案。 无论如何。
继续关于将Local处理程序转换为Persistent的回答。 在Node.js C ++插件文档页面上有一些例子:
https://nodejs.org/api/addons.html#addons_function_factory
对于持久对象,它们使用静态构造函数方法Persistent <Function> 。 当模块被inited构造函数可以通过像这样的Reset方法初始化(实际上我没有在v8 docs中find它的描述 – 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 handle cast:
Local<Function> f = Local<Function>::New(isoloate,persistentCallback)
注意你不能使用Handle指针,因为它的:: New方法不适合这样的参数。
BTW。 我想,我不需要在我的代码中使用持久化处理程序来存储callback方法,以防我已经将其绑定到JS上下文中。 在这种情况下,似乎是由GC妥善pipe理的。 但是没有其他方法可以在c ++函数调用之间共享variables,例如。 当你存储一些受保护的数据在你的模块。
我认为你应该将Local<T>
为Persistent<T>
然后将它们存储到events
。 如果你没有从v8的GC可以随时收集function。
Handle<Function> args0 = Handle<Function>::Cast(args[0]); Persistent<Function> pfn(args0); callback cb = callback(isolate, pfn); // use Persistent<T> instead of Local<T>