从node.js原生附加元件通知javascript(c++)

eh57zj3b  于 2022-11-03  发布在  Node.js
关注(0)|答案(1)|浏览(152)

我对javascript没有太多的了解。我用C++编写了一个共享库,它在守护进程线程中做某些事情。我需要从javascript中调用它。通过使用SWIG,我已经成功地生成了一个 Package 器,并使用node-gyp将我的代码与它沿着编译到.node模块中(也为它写了binding.gyp)。现在我可以下降到节点提示符,并做如下操作:

> var a = require("./module_name")
> a.SomeCppFunction("SomeString")

并很好地调用cpp函数,在那里启动一个分离的线程,并将控制返回给javascript。然而,我想从分离的cpp线程通知javascript有关的东西。我试图通过收集void(*fp)()等中的function() {}签名类型来注册javascript函数,以便稍后从c++中调用它们,但这不起作用。有没有任何办法能够实现这个ie.,在cpp代码中注册javascript函数(或其他函数)作为回调函数?

lpwwtiir

lpwwtiir1#

你可以使用SWIG和Napi的组合。一个现有的回购协议可以做到这一点,它是可用的here,一个博客here。但我会在这里总结的过程。
创建要在SWIG中使用的类,SWIG有一个在threadMain方法中运行的线程:


# include <Thread.H>

class Test : public ThreadedMethod {

  void *threadMain(void);

public:
  Test();

  void setFnPointer(const char* s);
};

现在,在Napi代码中,您将生成如下所示的线程安全函数:

Napi::ThreadSafeFunction tsfn; ///< The node api's threadsafe function

Napi::Value Start( const Napi::CallbackInfo& info ){
  Napi::Env env = info.Env();
  // Create a ThreadSafeFunction
  tsfn = Napi::ThreadSafeFunction::New(env,
    info[0].As<Napi::Function>(),  // JavaScript function to call
    "Resource Name", 0,1);

  // return the tsfn as a pointer in a string
  char addr[24];
  sprintf(addr,"%p",&tsfn);
  return Napi::String::New(env, addr);
}

// some small code to call NODE_API_MODULE here, check the file NapiCode.C in the repo

您将SWIG代码编译到一个模块,将Napi代码编译到另一个模块,然后将线程安全函数指针从一个模块传递到另一个模块,如下所示:

var libNapiNodejs = require('../swig/.libs/libNapiNodejs');
let fp = libNapiNodejs.start(function () {
    console.log("JavaScript callback called with arguments", Array.from(arguments));
}, 5);

// SWIG get our C++ and thread running
var libSwigCNodejs = require('../swig/.libs/libSwigCNodejs');
let test = new libSwigCNodejs.Test;

test.setFnPointer(fp); // tell swig the callback function pointer to execute
test.run(); // run the C++ thread in the SWIG module

您将看到C线程调用javascript函数,这是SWIG中的C线程:

Napi::ThreadSafeFunction *tsfn; ///< The node api's threadsafe function
void *Test::threadMain(void){
  printf("C++ Thread enter %s\n",__func__);
  auto callback = []( Napi::Env env, Napi::Function jsCallback, int* value ) {

    jsCallback.Call( {Napi::Number::New( env, *value )} );
  };

  for (int i=0; i<10; i++){
    sleep(1);
    if (*tsfn) {
      printf("calling tsfn->BlockingCall\n");
      napi_status status = tsfn->BlockingCall( &i, callback );
      if ( status != napi_ok ) // Handle error
        break;
    }
  }
  tsfn->Release();
  printf("C++ Thread exit %s\n",__func__);
  return NULL;
}

相关问题