在前 3 小结笔者简单介绍了 NAPI 工程并对生成的源码进行了简单介绍,本节笔者在前 3 小节的基础上对 NAPI 工程做个扩展,再额外添加一个计算 MD5 的方法 md5()
。
声明md5方法
在 index.d.ts 文件中声明一个 md5()
方法,该方法接收一个 string 参数,返回类型也是 string 类型,表示经过 MD5 计算后的值,样例代码如下所示:
export const add: (a: number, b: number) => number;
// 声明 md5 方法
export const md5: (value: string) => string;
映射C++方法
在前 3 节的介绍中我们知道,JS 端声明的方法由 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()
方法的解释说明的很清楚:第 1 步从 napi_callback_info
中读取传递进来的参数放入 args
中;第 2 步读取传递的参数类型;第 3 步判断参数类型是否为 null
,如果为 null
则抛异常;第 4 步读取参数长度;第 5 步如果传递的参数为 ""
则抛异常;第 6 步根据参数长度把参数读取出来放入 buffer
里,第 7 布模拟 MD5 操作直接在参数末尾追加 [NAPI]
字符串,第 8 步把 C++ 类型转换成 napi_value
类型,第 9 布清理资源,第 10 步返回结果。
📢:读取 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)
小结
本节笔者在前 3 小节的基础上简单实现了 C++ 端的 md5()
方法并实现 JS 端调用,该 md5()
方法是一个模拟,目的是跑通 JS 到 C++的调用流程,下节笔者将要介绍如何引入三方库实现真正的 MD5 计算。
码牛课堂也为了积极培养鸿蒙生态人才,让大家都能学习到鸿蒙开发最新的技术,针对一些在职人员、0基础小白、应届生/计算机专业、鸿蒙爱好者等人群,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线。大家可以进行参考学习:https://qr21.cn/FV7h05
①全方位,更合理的学习路径:
路线图包括ArkTS基础语法、鸿蒙应用APP开发、鸿蒙能力集APP开发、次开发多端部署开发、物联网开发等九大模块,六大实战项目贯穿始终,由浅入深,层层递进,深入理解鸿蒙开发原理!②多层次,更多的鸿蒙原生应用:
路线图将包含完全基于鸿蒙内核开发的应用,比如一次开发多端部署、自由流转、元服务、端云一体化等,多方位的学习内容让学生能够高效掌握鸿蒙开发,少走弯路,真正理解并应用鸿蒙的核心技术和理念。③实战化,更贴合企业需求的技术点:
学习路线图中的每一个技术点都能够紧贴企业需求,经过多次真实实践,每一个知识点、每一个项目,都是码牛课堂鸿蒙研发团队精心打磨和深度解析的成果,注重对学生的细致教学,每一步都确保学生能够真正理解和掌握。
为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05
《鸿蒙开发学习手册》:https://qr21.cn/FV7h05
如何快速入门:
- 基本概念
- 构建第一个ArkTS应用
- ……
开发基础知识:https://qr21.cn/FV7h05
- 应用基础知识
- 配置文件
- 应用数据管理
- 应用安全管理
- 应用隐私保护
- 三方应用调用管控机制
- 资源分类与访问
- 学习ArkTS语言
- ……
基于ArkTS 开发:https://qr21.cn/FV7h05
- Ability开发
- UI开发
- 公共事件与通知
- 窗口管理
- 媒体
- 安全
- 网络与链接
- 电话服务
- 数据管理
- 后台任务(Background Task)管理
- 设备管理
- 设备使用信息统计
- DFX
- 国际化开发
- 折叠屏系列
- ……
鸿蒙开发面试真题(含参考答案):https://qr21.cn/FV7h05
大厂鸿蒙面试题::https://qr18.cn/F781PH
鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH
1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向