鸿蒙5 汽车行业实践的常见问题-如何实现ArkTS到Native的跨模块长调用
📢 重磅福利!参与活动赢好礼,马克杯、鼠标垫,8月1日-12月31日等你来!
点击链接: 官方班级名称:HarmonyOS赋能资源丰富度建设(第四期)-GitCode
问题现象
整个调用链为hap ArkTS->har ArkTS->har Native侧->harArkTS。设定hap模块为entry。
- entry模块ArkTS调用har ArkTS侧A.ets页面导出的接口。
- har ArkTS侧A.ets页面中接口调用har Native侧的方法。
- har Native侧方法通过napi_load_module_with_info来加载har ArkTS侧B.ets导出的自定义接口。

har的ArkTS侧将函数包裹在命名空间中导出,其Native侧用napi_get_named_property加载函数,加载失败。
问题代码示例参考如下:
- // har包的ObjectUtil.ets
- namespace ObjectUtil {
- export function testOne() {
- console.info('你好,世界!')
- }
- }
- export { ObjectUtil }
- // har包的napi_init.cpp
- static napi_value loadModule(napi_env env, napi_callback_info info) {
- napi_value result;
- // 1.使用napi_load_module_with_info加载Test文件中的模块
- napi_status status = napi_load_module_with_info(env, "myTest_sdk/src/main/ets/common/ObjectUtil",
- "com.example.sodemo/myTest_sdk", &result);
- if (status != napi_ok) {
- return nullptr;
- }
- napi_value testFn;
- // 2.使用napi_get_named_property获取test函数
- status = napi_get_named_property(env, result, "testOne", &testFn); // 获取失败,status:napi_object_expected
- if (status != napi_ok) {
- return nullptr;
- }
- // 3.使用napi_call_function调用函数test
- status = napi_call_function(env, result, testFn, 0, nullptr, nullptr);
- if (status != napi_ok) {
- return nullptr;
- }
- return result;
- }
背景知识
应用开发中往往是由多个业务组共同完成一个APP的开发,每个业务组都有自己的工程,业务组会以HSP或har包的形式提供SDK能力给各个hap模块使用,这些SDK往往会提供C++接口或ets接口供其他模块直接调用。
Node-API中的napi_load_module_with_info接口的功能是进行模块的加载,当模块加载出来之后,可以使用函数napi_get_property获取模块导出的变量,也可以使用napi_get_named_property获取模块导出的函数。
- napi_status napi_load_module_with_info(napi_env env, const char* path, const char* module_info, napi_value* result);
|
参数 |
说明 |
|---|---|
|
env |
当前的虚拟机环境。 |
|
path |
加载的文件路径或者模块名。 |
|
module_info |
bundleName/moduleName的路径拼接。 |
|
result |
加载的模块。 |
解决方案
- har的ArkTS侧导出接口时包裹了一层namespace,Native侧在加载时需要用napi_get_named_property()先获取到命名空间对象,再去获取函数对象(一共获取两次),无法直接获取函数。
- har是集成到hap中的,其入口模块是hap,即entry模块。napi_load_module_with_info中:
- path:加载文件路径或者moduleName。注意此处的moduleName指的是入口模块(即entry模块)中oh-package.json5中dependencies标签下为har定义的名称,而不是har模块的实际名称。
- // hap(即entry模块)的oh-package.json5
- {
- "name": "entry",
- "version": "1.0.0",
- // ...
- "dependencies": {
- "lib_myTest_sdk": "file:../myTest_sdk"
- }
- }
path参数中的moduleName为lib_myTest_sdk,而非myTest_sdk。path:“lib_myTest_sdk/src/main/ets/common/ObjectUtil”,非“myTest_sdk/src/main/ets/common/ObjectUtil”。
- module_info:“bundleName/moduleName”的路径拼接。此处的moduleName指的是待加载模块所在的hap下module.json5中配置的名字。
- // hap(即entry模块)的module.json5
- {
- "module": {
- "name": "entry",
- "type": "entry",
- "description": "$string:module_desc",
- // ...
- }
- }
module_info参数中的moduleName为入口模块的模块名entry,而非har的模块名myTest_sdk。module_info:com.example.sodemo/entry,非com.example.sodemo/myTest_sdk。
- path:加载文件路径或者moduleName。注意此处的moduleName指的是入口模块(即entry模块)中oh-package.json5中dependencies标签下为har定义的名称,而不是har模块的实际名称。
- 完整示例参考如下:
- // har包的napi_init.cpp
- static napi_value loadModule(napi_env env, napi_callback_info info) {
- napi_value result;
- // 1.使用napi_load_module_with_info加载Test文件中的模块
- napi_status status = napi_load_module_with_info(env, "lib_myTest_sdk/src/main/ets/common/ObjectUtil",
- "com.example.sodemo/entry", &result);
- if (status != napi_ok) {
- return nullptr;
- }
- napi_value testNamespace;
- napi_value testFn;
- // 2.使用napi_get_named_property获取命名空间对象
- status = napi_get_named_property(env, result, "ObjectUtil", &testNamespace);
- if (status != napi_ok) {
- return nullptr;
- }
- // 3.使用napi_get_named_property获取test函数
- status = napi_get_named_property(env, testNamespace, "testOne", &testFn);
- if (status != napi_ok) {
- return nullptr;
- }
- // 4.使用napi_call_function调用函数test
- status = napi_call_function(env, testNamespace, testFn, 0, nullptr, nullptr);
- if (status != napi_ok) {
- return nullptr;
- }
- return result;
- }
更多推荐

所有评论(0)