yunnysunny yunnysunny - 2 months ago 12
C++ Question

use libuv function in node.js 0.12.x

I have written a node.js's c++ addon,i can be complied successfully under node.js 0.10.x. But when migrate it to 0.12.x, it failed when several error,such as

error C2065: “uv_work_t”:undeclared identifier
.I wonder whether i can touch libuv's api in 0.12.x?

The code is showed as follow:

#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.

Answer

just adding #include <uv.h> to the begin of the code can resolve the problem.