harmony 鸿蒙安全和高效的使用N-API开发Native模块_鸿蒙native开发(1)

napi_deferred deferred = nullptr;
napi_ref callback = nullptr;

double args[2] = {0};
double result = 0;

};

// 2、执行耗时任务,并将执行结果传递给 promise;
static void addExecuteCB(napi_env env, void *data) {
AddonData *addonData = (AddonData *)data;
addonData->result = addonData->args[0] + addonData->args[1];
};

// 3、使用 napi_resolve_deferred 或 napi_reject_deffered 接口来 resolve 或 reject 创建的 promise,并释放 deferred 对象;
static void addPromiseCompleteCB(napi_env env, napi_status status, void *data) {
AddonData *addonData = (AddonData *)data;
napi_value result = nullptr;
napi_create_double(env, addonData->result, &result);
napi_resolve_deferred(env, addonData->deferred, result);

if (addonData->callback != nullptr) {
    napi\_delete\_reference(env, addonData->callback);
}

// 删除异步 work
napi\_delete\_async\_work(env, addonData->asyncWork);
delete addonData;
addonData = nullptr;

};

// 1、用 napi_create_promise 接口创建 promise,将创建一个 deferred 对象并与 promise 一起返回,deferred
// 对象会绑定到已创建的 promise;
static napi_value addPromise(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
napi_value thisArg = nullptr;
napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr);

napi_valuetype valuetype0;
napi\_typeof(env, args[0], &valuetype0);
napi_valuetype valuetype1;
napi\_typeof(env, args[1], &valuetype1);
if (valuetype0 != napi_number||valuetype1 != napi_number) {
    napi\_throw\_type\_error(env, nullptr, "Wrong arguments. 2 numbers expected.");
    return NULL;
}

napi_value promise = nullptr;
napi_deferred deferred = nullptr;
napi\_create\_promise(env, &deferred, &promise);

// 异步工作项上下文用户数据,传递到异步工作项的execute、complete之间传递数据
auto addonData = new AddonData{
    .asyncWork = nullptr,
    .deferred = deferred,
};

napi\_get\_value\_double(env, args[0], &addonData->args[0]);
napi\_get\_value\_double(env, args[1], &addonData->args[1]);

// 创建async work,创建成功后通过最后一个参数(addonData->asyncWork)返回async work的handle
napi_value resourceName = nullptr;
napi\_create\_string\_utf8(env, "addAsyncCallback", NAPI_AUTO_LENGTH, &resourceName);
napi\_create\_async\_work(env, nullptr, resourceName, addExecuteCB, addPromiseCompleteCB, (void \*)addonData,
                       &addonData->asyncWork);

// 将刚创建的async work加到队列,由底层去调度执行
napi\_queue\_async\_work(env, addonData->asyncWork);

return promise;

}


在异步操作完成后,回调函数将被调用,并将结果传递给 Promise 对象。在 JavaScript 中,可以使用 Promise 对象的 then() 方法来处理异步操作的结果。



import hilog from ‘@ohos.hilog’;
import testNapi from ‘libentry.so’

@Entry
@Component
struct TestAdd {
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Text(“hello world”)
.onClick(() => {
let num1 = 2;
let num2 = 3;
testNapi.addPromise(num1, num2).then((result) => {
hilog.info(0x0000, ‘testTag’, ‘%{public}d’, result);
})
})
}
.width(‘100%’)
.height(‘100%’)
}
}


#### 指定异步任务调度优先级


Function Flow 编程模型(Function Flow Runtime,FFRT)是一种基于任务和数据驱动的并发编程模型,允许开发者通过任务及其依赖关系描述的方式进行应用开发。方舟 ArkTS 运行时提供了扩展 qos 信息的接口,支持传入 qos,并调用 FFRT,根据系统资源使用情况降低功耗、提升性能。


* 接口示例:napi\_status napi\_queue\_async\_work\_with\_qos(napi\_env env, napi\_async\_work work, napi\_qos\_t qos)()


	+ [in] env:调用API的环境;
	+ [in] napi\_async\_work: 异步任务;
	+ [in] napi\_qos\_t: qos 等级;
* qos 等级定义:



typedef enum {
napi_qos_background = 0,
napi_qos_utility = 1,
napi_qos_default = 2,
napi_qos_user_initiated = 3,
} napi_qos_t;

* N-API 层封装了对外的接口,对接 libuv 层 uv\_queue\_work\_with\_qos(uv\_loop\_t\* loop, uv\_work\_t\* req, uv\_work\_cb work\_cb, uv\_after\_work\_cb after\_work\_cb, uv\_qos\_t qos) 函数。
* 相较于已有接口 napi\_queue\_async\_work,增加了 qos 等级,用于控制任务调度的优先级。使用示例: “`cpp static void PromiseOnExec(napi\_env env, void \*data) { OH\_LOG\_INFO(LOG\_APP, “PromiseOnExec”); }



static void PromiseOnComplete(napi_env env, napi_status status, void *data) {
int number = *((int *)data); OH_LOG_INFO(LOG_APP, “PromiseOnComplete number = %{public}d”, number);
}

static napi_value Test(napi_env env, napi_callback_info info) {
napi_value resourceName = nullptr;
napi_create_string_utf8(env, “TestExample”, NAPI_AUTO_LENGTH, &resourceName);
napi_async_work async_work; int *data = new int(10); napi_create_async_work(env, nullptr, resourceName, PromiseOnExec, PromiseOnComplete, data, &async_work);
napi_queue_async_work_with_qos(env, async_work, napi_qos_default); return nullptr;
}


### 线程安全


如果应用需要进行大量的计算或者 IO 操作,使用并发机制可以充分利用多核 CPU 的优势,提高应用的处理效率。例如,图像处理、视频编码、数据分析等应用可以使用并发机制来提高处理速度。


虽然 N-API 本身不支持多线程并发操作,但是可以在多线程环境下进行一些数据交互,且需要格外注意线程安全。在多线程环境下,开发者可以使用 napi\_create\_threadsafe\_function 函数创建一个线程安全函数,然后在任意线程中调用。


\*\*应用场景:\*\*当 native 侧有其他线程,并且需要根据这些线程的完成结果调用 JavaScript 函数时,这些线程必须与 native 侧的主线程进行通信,才能在主线程中调用 JavaScript 函数。线程安全函数便提供了一种简化方法,避免了线程间通讯,同时可以回到主线程调用 JavaScript 函数。


#### 使用方法


##### ArkTS 侧传入回调函数



struct Index {
@State message: string = ‘Hello World’

build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
testNapi.threadSafeTest((value) => {
hilog.info(0x0000, ‘testTag’, 'js callback value = ’ + value);
})
})
}
.width(‘100%’)
}
.height(‘100%’)
}
}


##### native 侧主线程中创建线程安全函数



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, "thread CallJs %{public}d.\n", this_id);
napi_status status;

status = napi\_get\_reference\_value(env, cbObj, &js_cb);

napi_valuetype valueType = napi_undefined;
napi\_typeof(env, js_cb, &valueType);
OH\_LOG\_INFO(LOG_APP, "CallJs js\_cb is napi\_function: %{public}d", valueType == napi_function);

OH\_LOG\_INFO(LOG_APP, "CallJs 0");
if (env != NULL) {
    napi_value undefined, js_the_prime;
    status = napi\_create\_int32(env, 666, &js_the_prime);
    OH\_LOG\_INFO(LOG_APP, "CallJs 1: %{public}d", status == napi_ok);
    status = napi\_get\_undefined(env, &undefined);
    OH\_LOG\_INFO(LOG_APP, "CallJs 2: %{public}d", status == napi_ok);

    napi_value ret;

    status = napi\_call\_function(env, undefined, js_cb, 1, &js_the_prime, &ret);
    OH\_LOG\_INFO(LOG_APP, "CallJs 3: %{public}d", status == napi_ok);
}

}

napi_threadsafe_function tsfn;

static napi_value ThreadSafeTest(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value js_cb, work_name;
napi_status status;

status = napi\_get\_cb\_info(env, info, &argc, &js_cb, NULL, NULL);
OH\_LOG\_INFO(LOG_APP, "ThreadSafeTest 0: %{public}d", status == napi_ok);

status = napi\_create\_reference(env, js_cb, 1, &cbObj);
OH\_LOG\_INFO(LOG_APP, "napi\_create\_reference of js\_cb to cbObj: %{public}d", status == napi_ok);

status =
    napi\_create\_string\_utf8(env, "Node-API Thread-safe Call from Async Work Item", NAPI_AUTO_LENGTH, &work_name);
OH\_LOG\_INFO(LOG_APP, "ThreadSafeTest 1: %{public}d", status == napi_ok);

std::thread::id this_id = std::this_thread::get\_id();
OH\_LOG\_INFO(LOG_APP, "thread ThreadSafeTest %{public}d.\n", this_id);

napi_valuetype valueType = napi_undefined;
napi\_typeof(env, js_cb, &valueType);
OH\_LOG\_INFO(LOG_APP, "ThreadSafeTest js\_cb is napi\_function: %{public}d", valueType == napi_function);

status = napi\_create\_threadsafe\_function(env, js_cb, NULL, work_name, 0, 1, NULL, NULL, NULL, CallJs, &tsfn);
OH\_LOG\_INFO(LOG_APP, "ThreadSafeTest 2: %{public}d", status == napi_ok);

}


##### 其他线程中调用线程安全函数



std::thread t( {
std::thread::id this_id = std::this_thread::get_id();
OH_LOG_INFO(LOG_APP, “thread0 %{public}d.\n”, this_id);
napi_status status;
status = napi_acquire_threadsafe_function(tsfn);
OH_LOG_INFO(LOG_APP, “thread1 : %{public}d”, status == napi_ok);
status = napi_call_threadsafe_function(tsfn, NULL, napi_tsfn_blocking);
OH_LOG_INFO(LOG_APP, “thread2 : %{public}d”, status == napi_ok);
});
t.detach();


#### 线程函数使用注意事项


在多线程环境下,需要避免使用共享的数据结构和全局变量,以免竞争和冲突。同时,需要确保线程之间的同步和互斥,以避免数据不一致的情况发生。除此之外,仍需注意:


* 对线程安全函数的调用是异步进行的,对 JavaScript 回调的调用将被放置在任务队列中;
* 创建 napi\_threadsafe\_function 时,可以提供 napi\_finalize 回调。当线程安全函数即将被销毁时,将在主线程上调用此 napi\_finalize 回调;
* 在调用 napi\_create\_threadsafe\_function 时给定了上下文,可以从任何调用 napi\_get\_threadafe\_function\_context 的线程中获取。


**为了能让大家更好的学习鸿蒙 (OpenHarmony) 开发技术,这边特意整理了《鸿蒙 (OpenHarmony)开发学习手册》(共计890页),希望对大家有所帮助:[`https://qr21.cn/FV7h05`]( )**


#### 《鸿蒙 (OpenHarmony)开发学习手册》:[`https://qr21.cn/FV7h05`]( )


**入门必看:[`https://qr21.cn/FV7h05`]( )**


1. 应用开发导读(ArkTS)
2. ……


![](https://img-blog.csdnimg.cn/img_convert/4991b6612f7848b8226a785e9bf2fbe9.webp?x-oss-process=image/format,png)


**HarmonyOS 概念:[`https://qr21.cn/FV7h05`]( )**


1. 系统定义
2. 技术架构
3. 技术特性
4. 系统安全


![](https://img-blog.csdnimg.cn/img_convert/53c5d7c674e3b2bf227cbf917fccef69.webp?x-oss-process=image/format,png)


**如何快速入门:[`https://qr21.cn/FV7h05`]( )**


1. 基本概念
2. 构建第一个ArkTS应用
3. 构建第一个JS应用
4. ……


![](https://img-blog.csdnimg.cn/img_convert/52d468782ba786e32203d4ea7c7afc2b.webp?x-oss-process=image/format,png)


**开发基础知识:[`https://qr21.cn/FV7h05`]( )**


1. 应用基础知识
2. 配置文件
3. 应用数据管理
4. 应用安全管理
5. 应用隐私保护
6. 三方应用调用管控机制
7. 资源分类与访问
8. 学习ArkTS语言
9. ……


![](https://img-blog.csdnimg.cn/img_convert/2e9f9af56c68d6b543f76207bccf7bab.webp?x-oss-process=image/format,png)


**基于ArkTS 开发:[`https://qr21.cn/FV7h05`]( )**


1. Ability开发
2. UI开发
3. 公共事件与通知
4. 窗口管理
5. 媒体
6. 安全
7. 网络与链接
8. 电话服务
9. 数据管理
10. 后台任务(Background Task)管理
11. 设备管理
12. 设备使用信息统计
13. DFX
14. 国际化开发
15. 折叠屏系列
16. ……


![](https://img-blog.csdnimg.cn/img_convert/1a53a915fa49ea95ad0f0ffa72873a8c.webp?x-oss-process=image/format,png)


### 总结


鸿蒙系统开发作为当下的一个风口,对于有志于投身技术领域的小白来说是一个难得的机遇。通过深入了解鸿蒙系统的技术优势和市场前景,你将能够做出明智的选择。记住,站在风口上,猪都能飞起来,而掌握鸿蒙开发技能,或许就是你起飞的翅膀。现在就开始行动吧!


**为了能让大家更好的学习鸿蒙 (OpenHarmony) 开发技术,这边特意整理了《鸿蒙 (OpenHarmony)开发学习手册》(共计890页),希望对大家有所帮助:[`https://qr21.cn/FV7h05`]( )**


#### 《鸿蒙 (OpenHarmony)开发学习手册》:[`https://qr21.cn/FV7h05`]( )


**入门必看:[`https://qr21.cn/FV7h05`]( )**


1. 应用开发导读(ArkTS)
2. ……


![](https://img-blog.csdnimg.cn/img_convert/4991b6612f7848b8226a785e9bf2fbe9.webp?x-oss-process=image/format,png)


**HarmonyOS 概念:[`https://qr21.cn/FV7h05`]( )**


1. 系统定义
2. 技术架构
3. 技术特性
4. 系统安全


![](https://img-blog.csdnimg.cn/img_convert/53c5d7c674e3b2bf227cbf917fccef69.webp?x-oss-process=image/format,png)


**如何快速入门:[`https://qr21.cn/FV7h05`]( )**


1. 基本概念
2. 构建第一个ArkTS应用
3. 构建第一个JS应用
4. ……


![](https://img-blog.csdnimg.cn/img_convert/52d468782ba786e32203d4ea7c7afc2b.webp?x-oss-process=image/format,png)


**开发基础知识:[`https://qr21.cn/FV7h05`]( )**


1. 应用基础知识
2. 配置文件
3. 应用数据管理
4. 应用安全管理
5. 应用隐私保护
6. 三方应用调用管控机制
7. 资源分类与访问
8. 学习ArkTS语言
9. ……


![](https://img-blog.csdnimg.cn/img_convert/2e9f9af56c68d6b543f76207bccf7bab.webp?x-oss-process=image/format,png)


**基于ArkTS 开发:[`https://qr21.cn/FV7h05`]( )**


1. Ability开发
2. UI开发
3. 公共事件与通知
4. 窗口管理
5. 媒体
6. 安全
7. 网络与链接
8. 电话服务
9. 数据管理
10. 后台任务(Background Task)管理
11. 设备管理
12. 设备使用信息统计
13. DFX
14. 国际化开发
15. 折叠屏系列
16. ……


![](https://img-blog.csdnimg.cn/img_convert/1a53a915fa49ea95ad0f0ffa72873a8c.webp?x-oss-process=image/format,png)



### 给大家的福利


**零基础入门**


对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。


![](https://img-blog.csdnimg.cn/img_convert/95608e9062782d28f4f04f821405d99a.png)


同时每个成长路线对应的板块都有配套的视频提供:


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a91b9e8100834e9291cfcf1695d8cd42.png#pic_center)


因篇幅有限,仅展示部分资料

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/topics/618540462)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值