如何从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>