2012-06-19 35 views
4

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

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

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

在发送()函数我需要调用本地函数在其他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函数访问请求 - >消息。

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

看来,主叫关请求 - 方法>消息导致上一个非常小的地址(可能在V8 /节点某处一个空指针引用)的访问冲突。所以直接使用request->消息一定是错误的。我知道要访问的回调函数,我需要这样做:

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

我需要使用右键:: GetCurrent() - >全局(),以由包裹关闭Object类的访问方法持久性模板?如果是这样,我该怎么做?

回答

4

SendMessageWorker代码不是在JavaScript的执行 - 什么uv_queue_workSendMessageWorker在一个单独的线程,因此它可以让Node.js的代码运行,以及,当它准备好了,SendMessageWorkerComplete是在执行回不被执行JavaScript线程。

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

+0

啊好的。这就说得通了。谢谢! – Zik

+0

快速跟进问题 - WorkerComplete函数使用HandleScope,我需要在最后调用scope.Close(),还是在范围超出范围时将其正确清理? – Zik

+0

HandleScope确保您在其存在期间创建的JavaScript变量将被垃圾收集。它通过析构函数关闭,所以如果你不想返回任何东西,你不必显式地调用Close()。如果你想返回一个JS变量,你必须调用scope.Close(变量),这样它才不会被垃圾回收。 –