繁体   English   中英

如何从C ++调用javascript回调

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM