NAPI执行上层回调时,如何获取env?

NAPI执行上层回调时,如何获取env

阅读 4.6k
avatarAI BotBETA

在使用 Node.js 的 N-API(Node.js Addon API)执行上层回调时,env 通常指的是 N-API 环境,它包含了与 V8 引擎交互所需的所有函数和数据结构。当你执行上层回调时,你通常需要传递 env 以便在回调函数中访问 Node.js 的运行时环境。

为了在执行上层回调时获取 env,你需要确保在调用回调函数之前将其作为参数传递。通常,在编写一个 N-API 插件时,你会在插件的初始化函数中创建一个上下文(context),并将 env 作为该上下文的一部分。然后,当你需要执行一个上层回调时,你可以从这个上下文中检索 env 并将其传递给回调函数。

这里是一个简化的示例,展示了如何在 N-API 中执行上层回调并传递 env

#include <node_api.h>

// 假设这是你的上层回调函数
void upperLayerCallback(napi_env env, void* data) {
    // 在这里你可以使用 env 来访问 N-API 的功能
    // ...
}

// 插件的初始化函数
napi_value Init(napi_env env, napi_value exports) {
    // 创建一个上下文,并将 env 保存到其中
    // ...

    // 假设你有一个需要执行上层回调的函数
    void* callbackData = /* ... */;

    // 执行上层回调,传递 env 和其他数据
    upperLayerCallback(env, callbackData);

    // ...
    return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

在这个示例中,upperLayerCallback 是你的上层回调函数,它接受一个 napi_env 参数来访问 N-API 功能。在插件的初始化函数 Init 中,你创建了一个上下文(虽然这里没有显式显示),并在执行上层回调时从该上下文中检索 env,然后将其传递给 upperLayerCallback

请注意,这个示例是非常简化的,实际的实现可能会更复杂,具体取决于你的插件的具体需求。此外,确保在回调函数中正确地处理 env,避免在不应该的时候释放或修改它。

1 个回答

libuv处理方式是在注册JS回调时保存env。在callback中从env中获取对应的JS线程的loop,再调用libuv接口抛JS任务到loop中执行。

napi_create_thread_safe_function函数调用是会触发参数中的napi_threadsafe_function_call_js函数,该函数可以获取env在js线程中执行,可参考如下方式:

#include "napi/native_api.h" 
#include <thread> 
#include "hilog/log.h" 
 
napi_ref cbObj = nullptr; 
// 线程安全函数 
napi_threadsafe_function tsfn; 
// Native侧Value值 
static int cValue; 
 
 
// 子线程运行函数 
static void CallJs(napi_env env, napi_value js_cb, void *context, void *data) { 
    std::thread::id this_id = std::this_thread::get_id(); 
    OH_LOG_INFO(LOG_APP, "threadId3 is +%{public}d", this_id); 
    // 获取引用值 
    napi_get_reference_value(env, cbObj, &js_cb); 
 
    // 创建一个ArkTS number作为ArkTS function的入参。 
    napi_value argv; 
    napi_create_int32(env, cValue, &argv); 
 
    napi_value result = nullptr; 
    napi_call_function(env, nullptr, js_cb, 1, &argv, &result); 
 
    napi_get_value_int32(env, result, &cValue); 
 
    napi_delete_reference(env, cbObj); 
} 
 
// Native 主线程 
static napi_value ThreadsTest(napi_env env, napi_callback_info info) { 
    // 从ArkTS侧获取的参数的数量 
    size_t argc = 1; 
    napi_value js_cb, work_name; 
 
    // 获取ArkTS参数 
    napi_get_cb_info(env, info, &argc, &js_cb, nullptr, nullptr); 
 
    // 指向napi_value js_cb 的 napi_ref cbObj 
    napi_create_reference(env, js_cb, 1, &cbObj); 
 
    // 通过UTF8编码的C字符串数据创建work_name 
    napi_create_string_utf8(env, "Work Item", NAPI_AUTO_LENGTH, &work_name); 
 
    // 创建线程安全函数 
    napi_create_threadsafe_function(env, js_cb, NULL, work_name, 0, 1, NULL, NULL, NULL, CallJs, &tsfn); 
 
    std::thread::id this_id = std::this_thread::get_id(); 
    OH_LOG_INFO(LOG_APP, "threadId1 is +%{public}d", this_id); 
 
    // 其他线程中调用线程安全函数 
    std::thread t([]() { 
        // 可获取线程ID 
        std::thread::id this_id = std::this_thread::get_id(); 
        OH_LOG_INFO(LOG_APP, "threadId2 is +%{public}d", this_id); 
        napi_acquire_threadsafe_function(tsfn); 
        napi_call_threadsafe_function(tsfn, NULL, napi_tsfn_blocking); 
    }); 
    t.detach(); 
 
    return NULL; 
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进