I am trying to setup a c++ application that should be able to invoke a function that is part of node.js module
While I could find example code on how to create C++ addons for node.js and also some examples on how to invoke V8 code from C++ I did not run into something like calling a node.js function from c++
I guess ideally the approach would be
Ideally the node.js code and the c++ code run in the same process context so that it is not necessary to marshall arguments and return values over some stream type of abstraction.
All tips welcome!
Tx
Peter
I eventually managed to get something going
What I struggled most with is how to deal with the node/v8 event loop so that it is started when the javascript function is invoked but also stops when the javascript function is done so that the calling c++ method continues....basically to wait for all the node async processing to be finished.
Briefly what I did is edit a c++ class that does something along the lines of
First initialize node, much like in node.cc methods Node::Init and Node::Start and passing in an argument pointing to a node script that defines the function I will want to call
Then register a C++ function in node's global namespace that will be used by the javascript function as a final callback. More or less like
v8::Locker locker;
v8::HandleScope handle_scope;
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
global->Set(v8::String::New("functionCallback"), v8::FunctionTemplate::New(fnCallback,v8::External::Wrap(this)));
Then invoke the javascript function
v8::Handle<v8::Value> value = global->Get(v8::String::New(functionName.c_str()));
v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value);
v8::Handle<v8::Value> *v8Args = new v8::Handle<v8::Value>[functionArguments.size()];
for (std::vector<std::string>::const_iterator it = functionArguments.begin(); it != functionArguments.end(); ++it) {
int ix = distance(functionArguments.begin(),it);
v8Args[ix] = v8::String::New((*it).c_str());
}
v8::Handle<v8::Value> fnResult;
fnResult = func->Call(global, functionArguments.size(), v8Args);
uv_run(uv_default_loop(),UV_RUN_DEFAULT);
It is important that the invoked javascript function eventually invokes the global callback, as in (javascript)
global.functionCallback(result);
This callback (c++) will then store the result and terminate the event loop
static v8::Handle<v8::Value> fnCallback(const v8::Arguments& args) {
...
// Stop node event loop so that the "calling" app continues (loop is started in execFn)
uv_stop(uv_default_loop());
...
I realize this is a bit terse. If someone is interested I can share the c++ class but my c++/v8/node knowledge is very limited so I'd rather not post that in its entirety
Peter
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With