积分166 / 贡献0

提问1答案被采纳1文章8

作者动态

[经验分享] Napi线程安全函数使用示例

深开鸿_苟晶晶 显示全部楼层 发表于 昨天 17:17

简介

napi如何使用线程安全函数。

文档环境

开发环境:Windows 10

DevEco Studio 版本:DevEco Studio 4.1 Release(4.1.0.400)

SDK 版本:API version 11 (4.1.7.5 Release)

开发板型号:DAYU200(RK3568)

OpenHarmony版本:OpenHarmony 5.0.2.51

使用示例

  1. 接口声明、编译配置、模块注册 接口声明

    export function startThreadsafefunc(callback: Callback<string>):void

    编译配置

    cmake_minimum_required(VERSION 3.4.1)
    project(MyApplication2)
    
    set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
    
    include_directories(${NATIVERENDER_ROOT_PATH}
                        ${NATIVERENDER_ROOT_PATH}/include)
    
    add_library(entry SHARED threadsafe4.cpp)
    target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so)

    模块注册

    EXTERN_C_START
    static napi_value Init(napi_env env, napi_value exports) {
        // Define properties and methods for a N-API object.
        napi_property_descriptor desc[] = {
            {"startThreadsafefunc", nullptr, StartThreadsafefunc, nullptr, nullptr, nullptr, napi_default, nullptr}
        };
        // Add an array of properties to a ArkTs object.
        napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
        return exports;
    }
    EXTERN_C_END
    
    static napi_module nativeModule = {
        .nm_version = 1,
        .nm_flags = 0,
        .nm_filename = nullptr,
        .nm_register_func = Init,
        .nm_modname = "entry",
        .nm_priv = nullptr,
        .reserved = { 0 },
    };
    
    extern "C" __attribute__((constructor)) void RegisterObjectWrapModule()
    {
        napi_module_register(&nativeModule);
    }
  2. 创建线程安全函数,

    struct MyContext {
        std::string importantString;
    };
    // Thread-safe JavaScript function object.
    napi_threadsafe_function g_threadsafeFunction;
    static void CallbackFunction(napi_env env, napi_value jsCallback, void *context, void *data)
    {
        size_t argc = 1;
        napi_value argv[1];
        int* aa = static_cast<int*>(data);
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "THREAD SAFE", "Native CallbackFunction *data: %{public}d", *aa);
        MyContext* myContext = static_cast<MyContext*>(context);
        napi_create_string_utf8(env, myContext->importantString.c_str(), NAPI_AUTO_LENGTH, &argv[0]);
        // Execute the callback function in a JavaScript environment. After the data is callbacked to JS, it will not wait for JS to finish executing.
        napi_call_function(env, nullptr, jsCallback, argc, argv, nullptr);
    }
    static void FinalizeFunction(napi_env env, void* data, void* hint)
    {
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "THREAD SAFE", "Native FinalizeFunction called.");
        MyContext* myContext = static_cast<MyContext*>(data);
        delete myContext;
    }
    static void ThreadFunction(void *data)
    {
        // Asynchronously call a JavaScript function in another thread.
        std::this_thread::sleep_for(std::chrono::seconds(1));
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "THREAD SAFE", "Native another thread sleep 1s.");
        // Invoke a JavaScript function asynchronously from a native thread. After this, it will execute CallbackFunction to callback data to js.
        int *param = new int(10);
        napi_call_threadsafe_function(g_threadsafeFunction, param, napi_tsfn_nonblocking);
        //  Decrement the reference count of a threadsafe function, potentially destroying it. After this, it will execute FinalizeFunction to release data.
        napi_release_threadsafe_function(g_threadsafeFunction, napi_tsfn_release);
    }
    napi_value StartThreadsafefunc(napi_env env, napi_callback_info info)
    {
        size_t argc = 1;
        napi_value args[1];
        napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
        MyContext* context = new MyContext{"Hello from C++"};
        napi_value name;
        napi_create_string_utf8(env, "testThreadsafefunc", NAPI_AUTO_LENGTH, &name);
        // Create a thread-safe function that can be called from worker threads.
        napi_create_threadsafe_function(env, args[0], nullptr, name, 0, 1,
            context, FinalizeFunction, context, CallbackFunction, &g_threadsafeFunction);
        // Start a new thread.
        std::thread newThread(ThreadFunction, nullptr);
        newThread.join();
        OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "THREAD SAFE", "Native main thread.");
        return nullptr;
    }

    调用流程:

    (1) 调用napi_create_threadsafe_function方法:注入线程安全的方法CallbackFunction,该方法按照nodejs文档要求的方法签名,定义为static void CallbackFunction(napi_env env, napi_value js_callback, void *context, void *data);第三个参数 *context 为创建该函数时传递的值,第四个参数 *data 为调用该函数的地方的自定义数据,然后将创建的CallbackFunction方法绑定到napi_threadsafe_function g_threadsafeFunction上。注入FinalizeFunction方法用于资源的清理,该方法按照nodejs文档要求的方法签名,定义为static void FinalizeFunction(napi_env env, void *data, void *hint );第二个参数 *data即为传递的需要释放的数据。

    (2) 新开一个线程B,在B线程中调用napi_call_threadsafe_function(g_threadsafeFunction, param, napi_tsfn_nonblocking); 其中param参数就是植入自定义数据的地方。主线程的CallbackFunction被napi主动调用,第四个参数 *data就是第三步的param;第三个参数 *context即为napi_create_threadsafe_function接口倒数第三个参数传递的值;在CallbackFunction可以对数据进行打印或者将数据回调到js层。

    (3) 在B线程中调用napi_release_threadsafe_function(g_threadsafeFunction, napi_tsfn_release);用于销毁线程安全函数,主线程的FinalizeFunction被napi主动调用进行资源的清理。

  3. ArkTS侧示例代码

    testNapi.startThreadsafefunc((res: string) => {
        console.log('THREAD SAFE console callback res is :', res);
    })
  4. 运行后,执行结果如下:

    A00000/THREAD SAFE             com.examp...lication  I     Native another thread sleep 1s.
    A00000/THREAD SAFE             com.examp...lication  I     Native main thread.
    A00000/THREAD SAFE             com.examp...lication  I     Native CallbackFunction *data: 10
    A03d00/JSAPP                   com.examp...lication  I     THREAD SAFE js callback res is : Hello from C++
    A00000/THREAD SAFE             com.examp...lication  I     Native FinalizeFunction called.

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部