Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

node.js Nan: call JavaScript callback in C++ function

I’m building a node-module wrapper for a C++ library to pass logging information through Nan to JavaScript. For this a NAN_Method is available to register a callback. The callback handler has to register itself as a callback at the C++ library via vlAddLogListener(). The LoggingCallbackHandler receives a message from the library at the function dispatchEvent, a C++ function. If I receive a log, I want to call the JavaScript callback to pass the data on.

The function dispatchEvent isn’t called in a Nan-context and therefore I don’t have a scope/context and no access to v8. How is it possible to call the JavaScript callback?

The code looks like this:

NAN_METHOD(registerLoggingCallback) 
{
    v8::Isolate* isolate = info.GetIsolate();
    v8::Local<v8::Function> fun = info[0].As<v8::Function>();
    lch = new LoggingCallbackHandler(isolate, fun);
}

LoggingCallbackHandler::LoggingCallbackHandler(v8::Isolate* isolate, v8::Local<v8::Function> fun) :
    _cb(isolate, fun)
{
    vlAddLogListener(&LoggingCallbackHandler::dispatchEvent, this);
}

void VL_CALLINGCONVENTION LoggingCallbackHandler::dispatchEvent(const char* eventData, void* clientData)
{
    // here I want to process the data and call the JavaScript callback
    v8::Local<v8::Function> f = v8::Local<v8::Function>::New(Nan::GetCurrentContext()->Global()->GetIsolate(), _cb);
    Nan::MakeCallback(Nan::GetCurrentContext()->Global(), f, argc, argv);
}
like image 471
S.B. Avatar asked Oct 17 '22 08:10

S.B.


1 Answers

Using Nan, you should save the function value using a Nan::Callback inside your registerLoggingCallback function :

Nan::Callback cb;
cb.Reset(info[0].As<v8::Function>());

Store this Nan::Callback inside your class. Modify your dispatchEvent function to use a uv_async_t to schedule a call to your callback to be run in the main thread.

The use of uv_async_t can be simplified using a Nan::AsyncWorker but you may be better off reading the documentation for a better understanding of how that works.

When you actually want to call the callback, you can do:

v8::Local<v8::Value> arg = Nan::Null();
cb.Call(1, &arg);

You can pass more values into the callback by passing an array of v8::Local<v8::Value> as the second parameter and increasing the first parameter accordingly.

like image 109
mkrufky Avatar answered Oct 21 '22 00:10

mkrufky