1、逻辑需求:
底层C/C++库需要初始化时,设置回调函数,供其它接口回调时使用,其它接口为异步调用。
2、大致实现逻辑
napi层
#include "napi/native_api.h"
#include <thread>
napi_ref cbObj = nullptr;
napi_threadsafe_function tsfn;
static void CallJs(napi_env env, napi_value js_cb, void *context, void *data) {
napi_get_reference_value(env, cbObj, &js_cb);
napi_value argv;
int i = (*(int *) data);
napi_create_int32(env, i, &argv);
napi_value result = nullptr;
napi_call_function(env, nullptr, js_cb, 1, &argv, &result);
}
static napi_value SetCallback(napi_env env, napi_callback_info info)
{
size_t argc = 1;
napi_value js_cb, work_name;
napi_status status;
napi_get_cb_info(env, info, &argc, &js_cb, nullptr, nullptr);
status = napi_create_reference(env, js_cb, 1, &cbObj);
// Set initial_refcount to 0 for a weak reference, >0 for a strong reference.
status = napi_create_reference(env, js_cb, 1, &cbObj);
status = napi_create_string_utf8(env, "Node-API Thread-safe call from Async work Item", NAPI_AUTO_LENGTH, &work_name);
status = napi_create_threadsafe_function(env, js_cb, NULL, work_name, 0, 1, NULL, NULL, NULL, CallJs, &tsfn);
return nullptr;
}
static void ThreadFunc(void){
int i = 0;
while (i < 10) {
i += 1;
napi_call_threadsafe_function(tsfn, &i, napi_tsfn_nonblocking);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
}
static napi_value MainThread(napi_env env, napi_callback_info info) {
ThreadFunc();
return nullptr;
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
napi_property_descriptor desc[] = {
{ "threadTest", nullptr, MainThread, nullptr, nullptr, nullptr, napi_default, nullptr },
{ "setCallback", nullptr, SetCallback, nullptr, nullptr, nullptr, napi_default, nullptr },
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END
static napi_module demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "threadtest",
.nm_priv = ((void*)0),
.reserved = { 0 },
};
extern "C" __attribute__((constructor)) void RegisterThreadtestModule(void)
{
napi_module_register(&demoModule);
}
复制
arkts层
worker.ets
import worker, { MessageEvents, ThreadWorkerGlobalScope } from '@ohos.worker';
import testNapi from 'libthreadtest.so';
import hilog from '@ohos.hilog';
const workerPort: ThreadWorkerGlobalScope = worker.workerPort;
workerPort.onmessage = (e: MessageEvents) => {
hilog.info(0x0000, 'testTag', e.data);
testNapi.threadTest();
}
复制
Index.ets
import hilog from '@ohos.hilog';
import testNapi from 'libthreadtest.so';
import worker, { ErrorEvent, MessageEvents } from '@ohos.worker';
import emitter from '@ohos.events.emitter';
let worker1: worker.ThreadWorker = new worker.ThreadWorker('threadtest/ets/workers/worker.ets', { name: "worker1" });
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
// 定义一个eventId为1的事件
event:emitter.InnerEvent = {
eventId: 1
};
// 收到eventId为1的事件后执行该回调
callback = (eventData:emitter.EventData) => {
hilog.info(0x0000, 'testTag', "callback: " + eventData.data?.msg);
this.message = 'callbackTimes : ' + eventData.data?.msg;
};
executeCallback(msg:number) {
hilog.info(0x3200, 'SD_PVD330', "executeCallback: " + msg + "\n");
// 定义一个eventId为1的事件,事件优先级为Low
let event:emitter.InnerEvent = {
eventId: 1,
priority: emitter.EventPriority.LOW
};
let eventData:emitter.EventData = {
data: {
"msg": msg
}
};
// 发送eventId为1的事件,事件内容为eventData
emitter.emit(event, eventData);
}
build() {
Row() {
Column() {
Text( this.message )
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
hilog.info(0x0000, 'testTag', 'before testNapi.threadTest');
worker1.postMessage('this is a msg to start worker1');
worker1.onmessage = (e: MessageEvents) => {
hilog.info(0x0000, 'testTag', "*******worker1 recv :" + e.data);
let num:number = e.data.data as number
this.message = 'callbackTimes : ' + num;
hilog.info(0x0000, 'testTag', this.message);
};
worker1.onerror = (e: ErrorEvent) => {
hilog.info(0x0000, 'testTag', "*******worker1 error :" + e.message);
}
hilog.info(0x0000, 'testTag', 'after testNapi.threadTest');
})
}
.width('100%')
}
.height('100%')
.onAppear(() => {
hilog.info(0x0000, 'testTag', 'onAppear');
emitter.on(this.event, this.callback);
testNapi.setCallback(this.executeCallback)
})
}
}
复制
其中,回调内用了消息订阅,将回调信息发送给主线程,这里是否需要消息订阅,还没测试