HarmonyOS鸿蒙Next中callback获取napi_env问题

HarmonyOS鸿蒙Next中callback获取napi_env问题 异步算子初始化后,通过Callback返回并通知js层,但是Callback没有napi_env无法,想咨询是否能全局持有napi_env或者是否有其他更优解决方案,代码如下:

// 算子初始化
_livenessChecker.Initialize({hunterModelPath, augustModelPath, alignModelPath, headPoseModelPath, eyeStateModelPath, pageantModelPath, livenessModelPath, colorModelPath, LivenessCallback, this});

// Callback
void LivenessCallback(CallbackEvent event, CallbackData callbackData, CallbackUserData callbackUserData) {
    // 希望能在这里使用 napi 相关接口,但是无法获取 nap_env
}

更多关于HarmonyOS鸿蒙Next中callback获取napi_env问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

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

struct CallbackContext {
    napi_env env = nullptr;
    napi_ref callbackRef = nullptr;
    int retData = 0;
};

static void callbackTest(CallbackContext * context) {
    std::thread::id this_id = std::this_thread::get_id();
    OH_LOG_INFO(LOG_APP, "thread id1 %d.\n", this_id);
    uv_loop_s * loop = nullptr;
    // 此处的env需要在注册JS回调时保存下来。从env中获取对应的JS线程的loop。
    napi_get_uv_event_loop(context-> env, &loop);

    uv_work_t * work = new uv_work_t;
    context-> retData = 1;
    work-> data = (void *)context;

    // 调用libuv接口抛JS任务到loop中执行。
    uv_queue_work(
        loop, work,
        [](uv_work_t * work) {},
        [](uv_work_t * work, int status) {
            CallbackContext *context = (CallbackContext *)work-> data;
    napi_handle_scope scope = nullptr;
    // 打开handle scope用于管理napi_value的生命周期,否则会内存泄露。
    napi_open_handle_scope(context-> env, &scope);
    if (scope == nullptr) {
        return;
    }

    napi_value callback = nullptr;
    napi_get_reference_value(context-> env, context-> callbackRef, &callback);
    napi_value retArg;
    napi_create_int32(context-> env, context-> retData, &retArg);
    napi_value ret;
    napi_call_function(context-> env, nullptr, callback, 1, &retArg, &ret);
    napi_delete_reference(context-> env, context-> callbackRef);

    // 关闭handle scope释放napi_value。
    napi_close_handle_scope(context-> env, scope);

    std::thread::id this_id = std::this_thread::get_id();
    OH_LOG_INFO(LOG_APP, "thread id2 %d.\n", this_id);

    // 释放work指针。
    if (work != nullptr) {
        delete work;
    }

    delete context;
    });

}

static napi_value JSTest(napi_env env, napi_callback_info info) {
    std::thread::id this_id = std::this_thread::get_id();
    OH_LOG_INFO(LOG_APP, "thread id0 %d.\n", this_id);

    size_t argc = 1;
    napi_value argv[1] = {0};
    napi_value thisVar = nullptr;
    void * data = nullptr;
    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);

    napi_valuetype valueType = napi_undefined;
    napi_typeof(env, argv[0], &valueType);
    if (valueType != napi_function) {
        return nullptr;
    }
    auto asyncContext = new CallbackContext();
    asyncContext-> env = env;
    napi_create_reference(env, argv[0], 1, &asyncContext-> callbackRef);

    std::thread testThread(callbackTest, asyncContext);
    testThread.detach();

    std::thread::id this_id2 = std::this_thread::get_id();
    OH_LOG_INFO(LOG_APP, "thread id3 %d.\n", this_id2);

    return nullptr;
}

开源三方库相关处理方式 https://gitee.com/openharmony-sig/ohos_ijkplayer/blob/master/ijkplayer/src/main/cpp/napi/ijkplayer_napi.cpp#L84

更多关于HarmonyOS鸿蒙Next中callback获取napi_env问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,napi_env 是 Node-API 的核心环境对象,用于管理 JavaScript 和 C/C++ 之间的交互。在回调函数中获取 napi_env 时,通常需要通过 napi_get_cb_info 函数来获取当前执行环境的上下文信息。napi_get_cb_info 是 Node-API 提供的一个函数,用于从回调函数中提取 napi_envthis 对象、参数等信息。

在鸿蒙Next中,napi_env 的管理和生命周期与标准的 Node-API 一致。回调函数在执行时,napi_env 会由鸿蒙Next的运行时自动传递给回调函数。开发者可以通过 napi_get_cb_info 在回调函数中获取 napi_env,并使用它来进行后续的 JavaScript 对象操作。

需要注意的是,napi_env 在多线程环境中是线程本地的,每个线程都有自己的 napi_env 实例。因此,在回调函数中获取的 napi_env 只能在当前线程中使用,不能跨线程共享。

在鸿蒙Next中,napi_env 的使用与其他平台的 Node-API 实现保持一致,开发者可以参考 Node-API 的官方文档来了解如何使用 napi_env 进行 JavaScript 和 C/C++ 之间的交互。

在HarmonyOS鸿蒙Next中,napi_env是NAPI(Native API)运行时的环境句柄,用于管理JavaScript与C/C++之间的交互。在回调函数中获取napi_env时,通常通过napi_get_cb_info函数从napi_callback_info中获取。确保在回调函数中正确使用napi_env,避免跨线程使用,因为它与特定的JavaScript上下文绑定。具体实现可参考鸿蒙官方文档和示例代码。

回到顶部