2015-05-09 31 views
3

我寫了一個node.js的C++插件,我可以在node.js 0.10.x下成功編譯。但是,當它遷移到0.12.x時,它會失敗,當幾個錯誤,如error C2065: 「uv_work_t」:undeclared identifier。我想知道我是否可以在0.12.x觸及libuv的api?
該代碼是顯示如下:在node.js中使用libuv函數0.12.x

#include <node.h> 
#include <string> 
#include <v8.h> 

#ifdef WINDOWS_SPECIFIC_DEFINE 
#include <windows.h> 
typedef DWORD ThreadId; 
#else 
#include <unistd.h> 
#include <pthread.h> 
typedef unsigned int ThreadId; 
#endif 
using namespace v8; 

void async_hello(const FunctionCallbackInfo<Value>& args); 

//not in main thread,called in uv thread pool 
void call_work(uv_work_t* req); 

//the callback function 
void call_work_after(uv_work_t* req); 

static ThreadId __getThreadId() { 
    ThreadId nThreadID; 
#ifdef WINDOWS_SPECIFIC_DEFINE 

    nThreadID = GetCurrentProcessId(); 
    nThreadID = (nThreadID << 16) + GetCurrentThreadId(); 
#else 
    nThreadID = getpid(); 
    nThreadID = (nThreadID << 16) + pthread_self(); 
#endif 
    return nThreadID; 
} 

static void __tsleep(unsigned int millisecond) { 
#ifdef WINDOWS_SPECIFIC_DEFINE 
    ::Sleep(millisecond); 
#else 
    usleep(millisecond*1000); 
#endif 
} 

//defined a struct to storage the async reqution information 
struct Baton { 

    //must be declared as the type of Persistent,when callback finished successfully,execute the function dispose to release. 
    Persistent<Function> callback; 

    // 
    bool error; 
    std::string error_message; 

    //save the string passed from js 
    std::string input_string; 

    //save the string return to js 
    std::string result; 

}; 


void async_hello(const Arguments& args) { 
    printf("\n%s Thread id : gettid() == %d\n",__FUNCTION__,__getThreadId()); 
    Isolate* isolate = Isolate::GetCurrent(); 
    HandleScope scope(isolate); 
    if(args.Length() < 2) { 
     ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); 
     return; 
     } 


    if (!args[0]->IsString() || !args[1]->IsFunction()) { 
     ThrowException(Exception::TypeError(
      String::New("Wrong number of arguments"))); 
     return; 
    } 


    Local<Function> callback = Local<Function>::Cast(args[1]); 

    Baton* baton = new Baton(); 
    baton->error = false; 
    baton->callback = Persistent<Function>::New(callback); 
    v8::String::Utf8Value param1(args[0]->ToString()); 
    baton->input_string = std::string(*param1); 

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

    int status = uv_queue_work(uv_default_loop(), req, call_work, 
           (uv_after_work_cb)call_work_after); 
    assert(status == 0); 
    return 
} 

//not in main thread 
void call_work(uv_work_t* req) { 
    printf("\n%s Thread id : gettid() == %d\n",__FUNCTION__,__getThreadId()); 
    Baton* baton = static_cast<Baton*>(req->data); 
    for (int i=0;i<15;i++) { 
     __tsleep(1000); 
     printf("sleep 1 seconds in uv_work\n"); 
    } 


    baton->result = baton->input_string+ "--->hello world from c++"; 

} 


//return to main thread 
void call_work_after(uv_work_t* req) { 
    printf("\n%s Thread id : gettid() == %d\n",__FUNCTION__,__getThreadId());  
    Isolate* isolate = Isolate::GetCurrent(); 
    HandleScope scope(isolate); 
    Baton* baton = static_cast<Baton*>(req->data); 
    if (baton->error) { 
     Local<Value> err = Exception::Error(String::New(baton->error_message.c_str())); 

     // 
     const unsigned argc = 1; 
     Local<Value> argv[argc] = { err }; 

     // 
     TryCatch try_catch; 

     baton->callback->Call(Context::GetCurrent()->Global(), argc, argv); 
     if (try_catch.HasCaught()) { 
      node::FatalException(try_catch); 
     } 
    } else { 

     const unsigned argc = 2; 
     Local<Value> argv[argc] = { 
      Local<Value>::New(Null()), 
      Local<Value>::New(String::New(baton->result.c_str())) 
     }; 
     TryCatch try_catch; 
     baton->callback->Call(Context::GetCurrent()->Global(), argc, argv); 
     if (try_catch.HasCaught()) { 
      node::FatalException(try_catch); 
     } 
    } 

    //relase Persistent callback 
    baton->callback.Dispose(); 
    // release the memory space 
    delete baton; 
    delete req; 
} 

void RegisterModule(Handle<Object> target) { 
    target->Set(String::NewSymbol("async_hello"),FunctionTemplate::New(async_hello)->GetFunction()); 
} 

NODE_MODULE(binding, RegisterModule); 

我已經改變async_hello的paramater,根據最新節點的API document,因爲它使用FunctionCallbackInfo(未在node.js中0.10.x使用Arguments)接收js的參數。原始代碼是存儲here,它可以在node.js 0.10.x下成功編譯。

+0

你能發表一些代碼嗎? libuv在nodejs 0.10和0.12之間改變,但工作隊列在其他部分發生了變化。 – staaar

+0

我已添加代碼 – yunnysunny

+0

您的代碼是異步回調的非常好的示例。 –

回答

3

只需將#include <uv.h>添加到代碼的開頭即可解決問題。