OpenHarmony ArkUI实战开发-NAPI方法扩展
在前三章节中, 笔者简要概述了NAPI工程并对其生成的源码进行了初步介绍. 在本章, 笔者在此基础上进一步阐述了NAPI工程的相关内容, 并新增了一个计算MD5的方法md5().
声明md5方法
在文件index.d.ts中定义一个md5()函数,并使其接受一个字符串类型的参数,并返回同样为字符串类型的值表示该字符串经过MD5计算后的结果
export const add: (a: number, b: number) => number;
// 声明 md5 方法
export const md5: (value: string) => string;
映射C++方法
在第1-3节中所述的知识中可知,在C++端实现时需要对两端的方法进行映射设置。因此,在hello.cpp文件的Init()方法内将MD5方法映射至C++中的Md5()函数即可完成跨端绑定配置。示例代码如下所示:
static napi_value Init(napi_env env, napi_value exports)
{
napi_property_descriptor desc[] = {
{ "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr },
// 设置JS的md5()方法的C++实现为Md5()方法,其它参数默认即可
{ "md5", nullptr, Md5, nullptr, nullptr, nullptr, napi_default, nullptr }
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
实现C++代码
在 Init() 方法中配置了 C++ 的 Md5() 方法后,需要实现 Md5() 方法,样例代码如下所示:
static napi_value Md5(napi_env env, napi_callback_info info) {
// 1、从info中取出JS传递过来的参数放入args
size_t argc = 1;
napi_value args[1] = { nullptr };
if (napi_ok != napi_get_cb_info(env, info, &argc, args, nullptr, nullptr)) {
napi_throw_error(env, "-1000", "napi_get_cb_info error");
return nullptr;
}
// 2、获取参数的类型
napi_valuetype stringType;
if (napi_ok != napi_typeof(env, args[0], &stringType)) {
napi_throw_error(env, "-1001", "napi_typeof error");
return nullptr;
}
// 3、如果参数为null,则抛异常
if (napi_null == stringType) {
napi_throw_error(env, "-1002", "the param can't be null");
return nullptr;
}
// 4、获取传递的string长度
size_t length = 0;
if (napi_ok != napi_get_value_string_utf8(env, args[0], nullptr, 0, &length)) {
napi_throw_error(env, "-1003", "napi_get_value_string_utf8 error");
return nullptr;
}
// 5、如果传递的是"",则抛异常
if (length == 0) {
napi_throw_error(env, "-1004", "the param length invalid");
return nullptr;
}
// 6、读取传递的string参数放入buffer中
char* buffer = new char[length + 1];
if (napi_ok != napi_get_value_string_utf8(env, args[0], buffer, length + 1, &length)) {
delete[] buffer;
buffer = nullptr;
napi_throw_error(env, "-1005", "napi_get_value_string_utf8 error");
return nullptr;
}
// 7、模拟MD5加密操作,直接给传递进来的string后追加[NAPI]
std::string str = buffer;
str = str + "[NAPI]";
// 8、把C++数据转成napi_value
napi_value value = nullptr;
const char* md5 = str.c_str();
if (napi_ok != napi_create_string_utf8(env, md5, strlen(md5), &value)) {
delete[] buffer;
buffer = nullptr;
napi_throw_error(env, "-1006", "napi_create_string_utf8 error");
return nullptr;
}
// 9、资源清理
delete[] buffer;
buffer = nullptr;
// 返回 value
return value;
}
对于Md5()方法而言其详细说明极为清晰:
首先从napi_callback_info中提取接收的数据并将其存入变量args中;
然后确定输入数据的数据类型;
接着检查输入数据类型是否为空若为空则抛出异常;
后续获取输入数据的具体长度;
若接收的数据为空字符串则抛出异常;
根据输入数据长度读取实际数据存入缓冲区中;
模拟MD5操作后直接在尾部追加[NAPI]字符串;
将C++类型转换为napi_value类型完成后续操作;
最后释放相关资源并返回计算结果
📢:读取 string 时先读取参数的长度,再读取内容。
测试C++方法
基于 Md5() 方法的实现中存在特定限制条件。具体而言,在函数执行时将不允许接收 null 类型或空字符串的数据类型作为输入,并且若输入有效值则会触发异常。进而可以验证以下三种情况:正常输入参数、传入 null 值以及提供空字符串参数。样例代码如下所示:
import testNapi from 'libentry.so'
@Entry @Component struct Index {
@State message: string = 'Hello,OpenHarmony'
build() {
Column({space: 10}) {
Text(this.message)
.fontSize(20)
Button("正常参数")
.onClick(() => {
this.message = testNapi.md5("Hello, OpenHarmony")
})
Button("null参数")
.onClick(() => {
this.message = testNapi.md5(null);
})
Button("\"\"参数")
.onClick(() => {
this.message = testNapi.md5("");
})
}
.padding(10)
.width('100%')
.height("100%")
}
}
点解 正常参数 按钮,样例运行结果如下所示:

点击 null参数 测试异常情况,异常日志如下:
02-28 23:50:56.176 2093-2093/com.example.oh_0400_napi E C03f00/ArkCompiler: [default] Call:1307 occur exception need return
02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: [jsi_base_utils.cpp(ReportJsErrorEvent)-(0)] summaryBody:
02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: Lifetime: 0.000000s
02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: Js-Engine: ark
02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: page: pages/Index.js
02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: Error message: the param can't be null
02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: SourceCode:
02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: this.message = testNapi.md5(null);
02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: ^
02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: Stacktrace:
02-28 23:50:56.177 2093-2093/com.example.oh_0400_napi E C03900/Ace: at anonymous (/ets/pages/Index.ets:20:26)
小结
本节中,在前三小节的基础上完成了C++端md5()函数的开发,并使JS端能够调用此md5()函数。此md5()函数模拟了从JS到C++的数据传递过程,并旨在演示JS与C++之间的接口调用机制。下一小节中将进一步讲解如何引入第三方库以实现真正的MD5计算功能。
如果想更深入的学习 OpenHarmony 开发的内容,可以参考以下学习文档:
OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

对OpenHarmony源代码深入解析:https://qr18.cn/CgxrRy
- 配置开发环境
- Windows 系统下的开发环境配置
- Ubuntu 系统的开发环境配置
- Linux 和 Windows 系统间的文件共享管理
- ……

系统架构分析:https://qr18.cn/CgxrRy
- 建立子系统模块
- 设计启动流程方案
- 实现Subsystems功能
- 开发分布式任务管理单元
- 实现数据传输管理模块
- 集成驱动功能模块
- ……

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

