You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Node-Addon-API从C++调用JS回调并避免多上下文覆盖?

解决多上下文C库调用JS回调被覆盖的问题

当前代码的核心问题是用全局变量存储JS回调,导致多个上下文(ctx1、ctx2)的回调互相覆盖。要让每个上下文的回调独立触发,需要把每个上下文对应的回调数据和C库句柄绑定,具体修改如下:

核心思路

不再使用全局变量存储回调,而是为每个上下文创建独立的回调数据结构体,将其作为userdata传递给C库的回调函数。这样C库触发事件时,能通过userdata找到当前上下文对应的JS回调。

修改后的代码实现

1. 定义回调数据结构体

封装每个上下文的N-API环境和持久化回调:

// 存储每个上下文的回调相关数据
struct CallbackData {
    Napi::FunctionReference callback;
    Napi::Env env;
    // 若C库在多线程触发回调,需添加ThreadSafeFunction:
    // Napi::ThreadSafeFunction tsfn;
};

2. 修改C库事件回调函数

从userdata中取出当前上下文的回调数据,调用对应的JS回调:

extern "C" void onEvent(mylib_t* handle, void* userdata) {
    CallbackData* data = static_cast<CallbackData*>(userdata);
    if (data != nullptr && !data->callback.IsEmpty()) {
        // 注意:多线程场景必须用ThreadSafeFunction调用,以下是单线程简化示例
        data->callback.Call({});
    }
}

3. 更新SetEventCallback方法

为每个上下文创建独立的回调数据,传递给C库并绑定内存清理逻辑:

Napi::Value MyWrapper::SetEventCallback(const Napi::CallbackInfo &info) {
    Napi::Env env = info.Env();
    mylib_t* handle = convertJSBigIntToHandle(info[0]);
    Napi::Function jsCallback = info[1].As<Napi::Function>();

    // 分配内存存储当前上下文的回调数据
    CallbackData* data = new CallbackData();
    data->env = env;
    data->callback = Napi::Persistent(jsCallback);
    // 可选:设置弱引用避免内存泄漏,需根据业务场景调整
    // data->callback.SetWeak();

    // 将回调数据作为userdata传给C库
    const auto ret = mylib_set_callback(handle, onEvent, data);

    // 绑定内存清理逻辑,上下文销毁时释放资源
    env.AddCleanupHook([](void* cleanupData) {
        CallbackData* cbData = static_cast<CallbackData*>(cleanupData);
        cbData->callback.Reset();
        delete cbData;
    }, data);

    return env.Null();
}

关键注意事项

  • 多线程安全:如果C库在非V8主线程触发事件,必须使用Napi::ThreadSafeFunction来调用JS回调,直接调用Call()会导致崩溃。需将结构体中的FunctionReference替换为ThreadSafeFunction,并通过BlockingCall或NonBlockingCall触发回调。
  • 内存管理:务必在上下文销毁或用户移除回调时释放CallbackData内存,避免内存泄漏。示例中通过AddCleanupHook监听环境销毁事件来自动清理。
  • 避免全局状态:每个上下文的回调数据独立存储,通过userdata与C库句柄绑定,彻底解决多上下文回调覆盖问题。

内容的提问来源于stack exchange,提问作者Alex Shaw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 06:25:20