8

也许我只是没有搜索正确的术语,但我被困住了..

我需要从 C++ 调用 JavaScript 函数,这与使用普通 C API可以完成的非常相似。

注意:我不想回调传递给 C++ 代码,但我已经知道要调用的函数的名称!

例如,我在 JavaScript 中有一个这样的函数:

function log_message_callback(context, message) {
  console.log(`${context}: ${message}`);
}

my_napi_module.initialize();   // <-- starts thread that would call log_message_callback

我想从 C++ 调用它(顺便说一句,来自与主线程不同的线程):

#include <napi.h>

void log_message_callback(char const* message) {
  // magic Napi code which would call log_message_callback in JavaScript
} 

void some_thread_fn() {
  log_message_callback("hello world");
}

我可以这样做吗?我该怎么做?我应该一直在寻找什么?!

4

2 回答 2

6

JavaScript 函数通常只能从本机插件的主线程调用。您可以从

. https://nodejs.org/dist/latest-v11.x/docs/api/n-api.html#n_api_asynchronous_thread_safe_function_calls

napi_call_function ()可用于从本机层调用 JavaScript 函数。该文档也有一个代码片段用于它的使用。 https://nodejs.org/dist/latest-v11.x/docs/api/n-api.html#n_api_napi_call_function

于 2019-08-12T21:31:15.903 回答
4

这不是答案- 只是一些研究成果..

看起来我必须编写的代码必须看起来像这样 - 目前我不知道如何设置所有工作..

大部分代码取自这个eventing fork

这些值必须可用 - 好像我必须在模块初始化中初始化它们..

static v8::Persistent<v8::Context> context_;
static v8::Isolate *isolate_;

这个函数既可以log_message_callback()从 JavaScript wold 转换为 a v8::Function也可以调用它。更复杂的方法会将这些步骤分开:

extern "C" {

void log_message_callback(char const* message) {
  v8::Locker locker(isolate_);
  v8::Isolate::Scope isolate_scope(isolate_);
  v8::HandleScope handle_scope(isolate_);
  auto context = context_.Get(isolate_);
  v8::Context::Scope context_scope(context);

  v8::Persistent<v8::Function> log_message_callback_fn;

  /// this is only needed once - just for demonstration
  {
    auto global = context->Global();
    v8::Local<v8::Value> log_message_callback_def;
    if (!global->Get(
          context, v8Str(isolate_, "log_message_callback")).ToLocal(&log_message_callback_def)) {
      return;
    }

    if (!log_message_callback_def->IsFunction()) {
      return;
    }


    if (log_message_callback_def->IsFunction()) {
      auto on_update_fun = log_message_callback_def.As<v8::Function>();
      log_message_callback_fn.Reset(isolate_, on_update_fun);
    }
  }  

  v8::Local<v8::Value> args[2];
  log_message_callback_fn.Get(isolate_)->Call(context->Global(), 2, args);
}
于 2019-08-08T09:35:54.067 回答