4

好的,我有一个需要从 JavaScript 调用的 C++ 函数,其中一个参数是 JavaScript 对象。JavaScript 看起来像这样:

var message = {
    fieldA: 42,
    fieldB: "moo"
};

myObj.send(message, function (err) { console.log("Result: " + err); });

在 send() 例程中,我需要调用另一个可能阻塞的 C 库中的本机函数。这个库中的所有函数都可能阻塞,所以我一直在广泛使用 uv_queue_work。

这个例程是我第一次遇到问题,这是因为 JavaScript 对象。C++ 代码如下所示:

struct SendMessageRequest
{
    Persistent<Object> message;
    Persistent<Function> callback;
    int result;
};

Handle<Value> MyObj::Send(const Arguments& args)
{
    HandleScope scope;

    // Parameter checking done but not included here
    Local<Object> message = Local<Object>::Cast(args[0]);
    Local<Function> callback = Local<Function>::Cast(args[1]);

    // Send data to worker thread
    SendMessageRequest* request = new SendMessageRequest;
    request->message = Persistent<Object>::New(message);
    request->callback = Persistent<Function>::New(callback);

    uv_work_t* req = new uv_work_t();
    req->data = request;

    uv_queue_work(uv_default_loop(), req, SendMessageWorker, SendMessageWorkerComplete);

    return scope.Close(Undefined());
}

这一切都很好,当我尝试在 SendMessageWorker 函数中访问 request->message 时,问题就来了。

void SendMessageWorker(uv_work_t* req)
{
    SendMessageRequest* request = (SendMessageRequest*)req->data;
    Local<Array> names = request->message->GetPropertyNames();
    // CRASH

似乎从 request->message 调用方法会导致在一个非常小的地址上发生访问冲突(可能是 V8/node 中某处的 NULL 指针引用)。所以直接使用request->message肯定是错的。我知道要访问我需要这样做的回调函数:

request->callback->Call(Context::GetCurrent()->Global(), 1, argv);

我是否需要使用 Context::GetCurrent()->Global() 来访问由 Persistent 模板包装的 Object 类的方法?如果是这样,我该怎么做?

4

1 回答 1

4

中的代码SendMessageWorker不在 JavaScript 上执行 -uv_queue_work所做的是在单独的线程中执行您SendMessageWorker的代码,因此它可以让 node.js 代码也运行,并且当它准备好时,SendMessageWorkerComplete在 JavaScript 线程上执行。

所以你不能在 SendMessageWorker 中使用 JavaScript 变量——如果你真的需要,你必须在调用之前将它们转换为例如 C++ 字符串uv_queue_work

于 2012-06-19T23:33:13.147 回答