4

我正在尝试设置一个 c++ 应用程序,该应用程序应该能够调用作为 node.js 模块一部分的函数

虽然我可以找到有关如何为 node.js 创建 C++ 插件的示例代码以及有关如何从 C++ 调用 V8 代码的一些示例,但我并没有遇到类似从 C++ 调用 node.js 函数的情况

我想理想情况下的方法是

  • 设置 node.js 环境,例如一次编译所有必要的模块
  • 当 C++ 应用程序需要时,调用带有参数的“可用”node.js 函数之一
  • 读取并处理函数的返回值

理想情况下,node.js 代码和 c++ 代码在相同的进程上下文中运行,这样就没有必要通过某种流类型的抽象来编组参数和返回值。

欢迎所有提示!

发送

彼得

4

1 回答 1

7

我最终设法让事情顺利进行

我最苦恼的是如何处理 node/v8 事件循环,以便在调用 javascript 函数时启动它,但在 javascript 函数完成时停止,以便调用 c++ 方法继续......基本上等待完成所有节点异步处理。

简而言之,我所做的是编辑一个 c++ 类,该类执行以下操作

  • 首先初始化节点,就像在 node.cc 方法 Node::Init 和 Node::Start 中一样,并传入一个指向节点脚本的参数,该脚本定义了我要调用的函数

  • 然后在节点的全局命名空间中注册一个 C++ 函数,该函数将被 javascript 函数用作最终回调。或多或少像

    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)));
    
  • 然后调用javascript函数

    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);
    
  • 重要的是被调用的 javascript 函数最终会调用全局回调,如 (javascript)

    global.functionCallback(result);
    
  • 然后这个回调(c++)将存储结果并终止事件循环

    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());
    ...
    

我意识到这有点简洁。如果有人感兴趣,我可以分享 c++ 类,但我的 c++/v8/node 知识非常有限,所以我宁愿不完整发布

彼得

于 2013-06-23T10:15:15.670 回答