简介
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
使用示例
-
接口声明、编译配置、模块注册
接口声明
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);
}
-
创建线程安全函数,
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主动调用进行资源的清理。
-
ArkTS侧示例代码
testNapi.startThreadsafefunc((res: string) => {
console.log('THREAD SAFE console callback res is :', res);
})
-
运行后,执行结果如下:
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.
|