从V8中的C ++回调调用Javascript函数 [英] Calling Javascript function from a C++ callback in V8

查看:241
本文介绍了从V8中的C ++回调调用Javascript函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在调用c ++回调时调用已注册的JS函数,但由于我认为是范围问题,因此我遇到了段错误.

I'm trying to call a registered JS function when a c++ callback is called, but I'm getting a segfault for what I assume is a scoping issue.

 Handle<Value> addEventListener( const Arguments& args ) {
    HandleScope scope;
    if (!args[0]->IsFunction()) {
        return ThrowException(Exception::TypeError(String::New("Wrong arguments")));
    }

    Persistent<Function> fn = Persistent<Function>::New(Handle<Function>::Cast(args[0]));
    Local<Number> num = Number::New(registerListener(&callback, &fn));
    scope.Close(num);
}

事件发生时,将调用以下方法.我假设这可能发生在V8正在执行JS的另一个线程上.

When an event happens, the following method is called. I'm assuming that this probably happens on another thread to which V8 is executing JS.

void callback(int event, void* context ) {
    HandleScope scope;
    Local<Value> args[] = { Local<Value>::New(Number::New(event)) };
    Persistent<Function> *func = static_cast<Persistent<Function> *>(context);
    (* func)->Call((* func), 1, args);

    scope.Close(Undefined());
}

这会导致分段错误:11.请注意,如果我直接使用addEventListener()中对Persistent的引用来调用回调函数,则它将正确执行该函数.

This causes a Segmentation fault: 11. Note that if I call the callback function directly with a reference to Persistent from addEventListener(), it executes the function correctly.

我假设我需要一个储物柜或隔离柜?看起来libuv的uv_queue_work()也许可以解决这个问题,但是由于我没有启动线程,所以我看不到您将如何使用它.

I'm assuming that I need a Locker or Isolate? It also looks like libuv's uv_queue_work() might be able to solve this, but since I don't start the thread, I can't see how you would use it.

推荐答案

在代码中声明Persistent<Function> fn时,fn是堆栈分配的变量.

When you declare Persistent<Function> fn in your code, fn is a stack-allocated variable.

fn是一个Persistent<Function>,它是一个 handle 类,它将包含一个指向某些类型为Function的堆分配值的指针,但是fn本身是打开的堆栈.

fn is a Persistent<Function>, which is a handle class, and it will contain a pointer to some heap-allocated value of type Function, but fn itself is on the stack.

这意味着,当您调用registerListener(&callback, &fn)时,&fn会使用句柄的地址(类型为Persistent<Function>),而不是堆上Function的地址.当函数退出时,句柄将被销毁,但Function本身将保留在堆中.

This means that when you call registerListener(&callback, &fn), &fn is taking the address of the handle (type Persistent<Function>), not the address of the Function on the heap. When your function exits, the handle will be destroyed but the Function itself will remain on the heap.

因此,作为修复,我建议传递Function的地址而不是句柄的地址,如下所示:

So as a fix, I suggest passing the address of the Function instead of the address of the handle, like this:

Persistent<Function> fn = Persistent<Function>::New(Handle<Function>::Cast(args[0]));
Local<Number> num = Number::New(registerListener(&callback, *fn));

(请注意,Persistent<T>上的operator*返回的是T*,而不是更传统的T&,请参见

(note that operator* on a Persistent<T> returns a T* rather than the more conventional T&, c.f. http://bespin.cz/~ondras/html/classv8_1_1Handle.html)

您还必须调整callback,以解决以下事实:context现在是指向Function的原始指针,如下所示:

You'll also have to adjust callback to account for the fact that context is now a raw pointer to a Function, like this:

Persistent<Function> func = static_cast<Function*>(context);
func->Call((* func), 1, args);

在这里从原始的函数指针创建Persistent<Function>是可以的,因为我们知道context实际上是一个持久对象.

Creating a Persistent<Function> from a raw Function pointer here is OK because we know that context is actually a persistent object.

为简便起见,我还将(*func)->Call(...)更改为func->Call(...);他们对V8手柄也做同样的事情.

I've also changed (*func)->Call(...) to func->Call(...) for brevity; they do the same thing for V8 handles.

这篇关于从V8中的C ++回调调用Javascript函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆