也许我只是没有搜索正确的词,但是我被困住了。
我需要从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
Run Code Online (Sandbox Code Playgroud)
从C ++我想调用它(顺便说一句,来自与主线程不同的线程):
function log_message_callback(context, message) {
console.log(`${context}: ${message}`);
}
my_napi_module.initialize(); // <-- starts thread that would call log_message_callback
Run Code Online (Sandbox Code Playgroud)
我可以这样做吗?我该怎么做?我应该一直在寻找什么?
我正在为 NodeJS 构建一个 C++ 插件,我想将数据从 C++ 异步传输到 Node。但是,我找到了这篇文章https://nodeaddons.com/streaming-data-into-a-node-js-c-addon/;我想使用 N-API 而不是 NAN。
我一直在搜索 NodeJS 文档和示例,并寻找其他资源和示例,但还没有找到一个资源来向我展示如何实现这一点。这是我第一次为 NodeJS 编写 C++ 插件。
一个可以帮助我入门的示例是一个插件,它使用 N-API 每秒向 Node 发送一个虚拟字符串,然后 Node 会将字符串打印到控制台。
设置:
我有一个 NODE.JS 应用程序,它必须以低延迟执行一些计算
我决定使用 N-API 和 node-gyp 将本机 C++ 模块包含到 NODE.JS 应用程序中
当前状态:
我到了工具链工作的地步,我可以将 C++ 源代码编译成二进制文件,在 NODE.JS 应用程序中包含二进制模块,NODE.JS 应用程序执行
我可以使用标准 NODE.JS 调用 C++ 方法来自 NODE.JS 的类型和方法可以在执行完成后将标准的 NODE.JS 类型返回给 NODE.JS
问题:
我不知道如何将自定义类型/对象从 C++
返回到 NODE.JS目前我想基本上返回一个具有多种类型的结构,以便将复杂解析的结果返回到 NODE.JS 中单个 NODE.JS 调用
最少的代码输出:
我做了一个最少的实现来演示我想做的事情。如果你评论#define ENABLE_RETURN_CLASS代码只使用标准的 NODE.JS 类型并且一切正常。在输出图像下方,显示工具链和执行按预期工作:

如果离开#define ENABLE_RETURN_CLASS,代码将无法编译。据我所知,它不明白如何从 C++ 对象转换为 NODE.JS 对象。这是错误:

最少代码:
初始化 NODE.JS 应用程序
npm init
npm install node-gyp --save-dev
npm install node-addon-api
Run Code Online (Sandbox Code Playgroud)
将 C++ 二进制文件编译为 NODE.JS 模块
npm run build
Run Code Online (Sandbox Code Playgroud)
启动 NODE.JS 应用程序
node main.js …Run Code Online (Sandbox Code Playgroud) 对于上下文,我从这个问题开始。我需要在另一个线程中调用发射器的回调。我做了一个最小的例子,但它出现了段错误emit.Call({cb, result});我的第一直觉是我的生命周期env或emit函数有问题。
插件.cpp
#include <napi.h>
#include <iostream>
#include <thread>
#include <memory>
#include <functional>
#include <chrono>
std::shared_ptr<std::thread> thread;
bool running = true;
void generate(Napi::Env& env, Napi::Function& emit)
{
while(running)
{
Napi::Array result = Napi::Array::New(env);
for(int i = 0; i < 3; ++i)
{
result[i] = rand()%100;
}
auto cb = Napi::String::New(env, "onFeedData");
emit.Call({cb, result});
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
Napi::Value Start(const Napi::CallbackInfo& info)
{
Napi::Env env = info.Env();
Napi::Function emit = info[0].As<Napi::Function>();
auto cb = …Run Code Online (Sandbox Code Playgroud) 我希望我的 C 库能够多次调用 JS 函数。我使用 Nan 让它工作,但在将其转换为 N-API/node-addon-api 时遇到问题。
如何保存 JS 回调函数并稍后从 C 调用它?
这是我使用 Nan 得到的结果:
Persistent<Function> r_log;
void sendLogMessageToJS(char* msg) {
if (!r_log.IsEmpty()) {
Isolate* isolate = Isolate::GetCurrent();
Local<Function> func = Local<Function>::New(isolate, r_log);
if (!func.IsEmpty()) {
const unsigned argc = 1;
Local<Value> argv[argc] = {
String::NewFromUtf8(isolate, msg)
};
func->Call(Null(isolate), argc, argv);
}
}
}
NAN_METHOD(register_logger) {
Isolate* isolate = info.GetIsolate();
if (info[0]->IsFunction()) {
Local<Function> func = Local<Function>::Cast(info[0]);
Function * ptr = *func;
r_log.Reset(isolate, func);
myclibrary_register_logger(sendLogMessageToJS);
} else { …Run Code Online (Sandbox Code Playgroud) 的文档AsyncContext具有可同步工作的此示例(仅作了少许修改,但仍可正常工作):
#include "napi.h"
void MakeCallbackWithAsyncContext(const Napi::CallbackInfo& info)
{
Napi::Function callback = info[0].As<Napi::Function>();
Napi::Object resource = info.Env().Global().As<Napi::Object>();;
Napi::AsyncContext context(info.Env(), "async_context_test", resource);
callback.MakeCallback(Napi::Object::New(info.Env()),
std::initializer_list<napi_value>{}, context);
}
Run Code Online (Sandbox Code Playgroud)
我想知道如何异步使用它-这是我的最新照片:
Napi::AsyncContext* _context;
Napi::FunctionReference* _callback;
Napi::Object* _resource;
void CallBack()
{
_callback->MakeCallback(*_resource, std::initializer_list<napi_value>{}, *_context);
}
void MakeCallbackWithAsyncContext(const Napi::CallbackInfo& info)
{
Napi::Function cb = info[0].As<Napi::Function>();
_callback = new Napi::FunctionReference(Napi::Persistent(cb));
_callback->SuppressDestruct();
_resource = new Napi::ObjectReference(Napi::Persistent(env.Global()));
_resource->SuppressDestruct();
_context = new Napi::AsyncContext(info.Env(), "async_context_test", _resource->Value());
// run CallBack() in different thread
}
Run Code Online (Sandbox Code Playgroud)
程序内部崩溃CallBack()。
我一直在浏览NAPI 文档,试图了解它是如何处理multithreading. 根据文档napi_create_threadsafe_function()和napi_call_threadsafe_function()用于js functions从多个线程创建和调用。问题是文档不是那么直截了当,并且没有示例,我在其他任何地方都找不到。
如果有人有任何使用经验napi_create_threadsafe_function()和/napi_call_threadsafe_function()或知道在哪里可以找到使用它们的示例。请如果你能帮助一个基本的例子,这样我就可以理解如何正确使用它们。
我正在C编写一个插件,而不是C++需要使用这些功能。我没有使用包装器node-addon-api,而是napi直接使用
我正在尝试使用 NAPI 创建节点模块。我必须创建返回承诺的异步函数。我不希望 testasynfunction 会阻塞 NodeJS 事件循环。do_something_asynchronous 是一个同步函数。
napi_deferred do_something_synchronous(napi_env env,napi_deferred deferred){
printf("\n3) Function called");
//napi_deferred deferred;
napi_value undefined;
napi_status status;
// Create a value with which to conclude the deferred.
status = napi_get_undefined(env, &undefined);
if (status != napi_ok) return NULL;
sleep(5);
// Resolve or reject the promise associated with the deferred depending on
// whether the asynchronous action succeeded.
if (false) {
printf("\n5) Success\nXXXXXXX");
status = napi_resolve_deferred(env, deferred, undefined);
} else {
printf("\nReject");
status = napi_reject_deferred(env, deferred, undefined);
} …Run Code Online (Sandbox Code Playgroud) 我在 Google Cloud Function (Node v10) 中遇到了本机模块依赖项(特别是 IBM MQ for js)的问题,并且没有找到我需要的任何信息,所以我打开了这个问题并回答了自己以允许其他人将来找到它。
它在 Node v8 引擎中运行良好,但现在已弃用。将引擎升级到 v10 并碰撞一些包(遵循有关我的依赖项的所有迁移指南)后,ffi-napi包在 期间抛出异常yarn install,如下所示:
ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: ...s status = napi_get_instance_data(env, &d);
^~~~~~~~~~~~~~~~~~~~~~
../src/ffi.cc:11:24: note: suggested alternative: 'napi_new_instance'
napi_status status = napi_get_instance_data(env, &d);
^~~~~~~~~~~~~~~~~~~~~~
napi_new_instance
../src/ffi.cc: In function 'Napi::Object BindingHook(Napi::Env, Napi::Object)':
../src/ffi.cc:347:24: error: 'napi_set_instance_data' was not declared in this scope
napi_status status = napi_set_instance_data(
^~~~~~~~~~~~~~~~~~~~~~
../src/ffi.cc:347:24: note: suggested alternative: 'napi_new_instance'
napi_status status = napi_set_instance_data(
^~~~~~~~~~~~~~~~~~~~~~
napi_new_instance
In file …Run Code Online (Sandbox Code Playgroud) node.js google-cloud-platform google-cloud-functions ibm-mq n-api
n-api ×9
node.js ×8
c++ ×4
asynchronous ×2
javascript ×2
c ×1
ibm-mq ×1
node-gyp ×1
promise ×1