开发某个小工具,需要在JavaScript(没错,为了使用element来写图形界面)中使用第三方SDK,该SDK中涉及到了C++多线程回调。学习了一下Node-API,成果如下:

为了让js那边传过来的函数可以在其他线程进行调用,首先需要把取到的函数转换为线程安全的

napi_get_cb_info(env,cbinfo,&argc,&js_cb,nullptr,nullptr); //获取js那边传来的回调
napi_create_threadsafe_function(env,js_cb,nullptr,cb_name,0,1,nullptr,nullptr,nullptr,&test,&func); //将其转化为线程安全的,关于test,和func参数的定义见下面区

全局定义线程安全函数变量,和它的回调函数

napi_threadsafe_function func;

void test(napi_env env, napi_value js_callback, void* context, void* data){
  napi_value name,undef,obj,val;
  napi_create_object(env,&obj);
  napi_create_string_utf8(env, "val", NAPI_AUTO_LENGTH, &val);
  napi_create_string_utf8(env, (char*)data, NAPI_AUTO_LENGTH, &name);
  napi_set_property(env,obj,val,name);
  napi_get_undefined(env,&undef);
  napi_call_function(env, undef, js_callback, 1,&obj, nullptr);
  delete[] data; //在这里删除了动态申请的data指向的空间
}

然后就可以在任何函数里调用我们的func回调了,完整代码如下,以供参考

#include <node_api.h>
#include <iostream>
#include <thread>
#include <string.h>
napi_threadsafe_function func;
void mycb(char *str){
  char *ip=new char[10];
  strcpy(ip,str);
  napi_call_threadsafe_function(func,ip,napi_tsfn_blocking);
}
void test(napi_env env, napi_value js_callback, void* context, void* data){
  napi_value name,undef,obj,val;
  napi_create_object(env,&obj);
  napi_create_string_utf8(env, "val", NAPI_AUTO_LENGTH, &val);
  napi_create_string_utf8(env, (char*)data, NAPI_AUTO_LENGTH, &name);
  napi_set_property(env,obj,val,name);
  napi_get_undefined(env,&undef);
  napi_call_function(env, undef, js_callback, 1,&obj, nullptr);
  delete[] data; 
}
void test2(void(*mycb)(char *str),char* p){
  mycb(p);
}
napi_value Method(napi_env env, napi_callback_info cbinfo) {
  napi_status status;
  size_t argc = 1;
  napi_value js_cb,global;
  napi_value cb_name;
  napi_create_string_utf8(env, "realpCb", NAPI_AUTO_LENGTH, &cb_name);
  napi_get_cb_info(env,cbinfo,&argc,&js_cb,nullptr,nullptr);
  napi_create_threadsafe_function(env,js_cb,nullptr,cb_name,0,1,nullptr,nullptr,nullptr,&test,&func);
  char a[]="123";
  char b[]="456";
  char c[]="789";
  std::thread pp(test2,mycb,a);
  std::thread pp1(test2,mycb,b);
  std::thread pp2(test2,mycb,c);
  pp.join();
  pp1.join();
  pp2.join();
  napi_release_threadsafe_function(func,napi_tsfn_release);
  return cb_name;
}

napi_value init(napi_env env, napi_value exports) {
  napi_status status;
  napi_value fn;

  status = napi_create_function(env, nullptr, 0, Method, nullptr, &fn);
  if (status != napi_ok) return nullptr;

  status = napi_set_named_property(env, exports, "hello", fn);
  if (status != napi_ok) return nullptr;
  return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, init)

实现了一个hello函数,该函数会执行三个子线程调用js端传来的回调,并将结果以Object的形式返回到JS端

var main=require("./main.node")
main.hello((res)=>{
    console.log(res)
})
process.on("exit",()=>{
    console.log("close");
})

Electron写界面和读Excel是真的香阿,方便写批量操作小工具哦