在 node.js 0.12.x 中使用 libuv 函数

use libuv function in node.js 0.12.x

我写了一个node.js的c++插件,在node.js0.10.x下可以编译成功。但是当它迁移到0.12.x时,它在几个错误时失败了,比如error C2065: “uv_work_t”:undeclared identifier。我想知道我是否可以在0.12.x中触摸libuv的api?
代码如下:

#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);

I have changed async_hello's paramater,since according to the newest node's API document,it use FunctionCallbackInfo(not Arguments used in node.js 0.10.x) to receive js's paramater.The original code is storage here, and it can be compiled successfully under node.js 0.10.x.

只需在代码开头添加 #include <uv.h> 即可解决问题。