📢 重磅福利!参与活动赢好礼,马克杯、鼠标垫,8月1日-12月31日等你来!
点击链接: 官方班级名称:HarmonyOS赋能资源丰富度建设(第四期)-GitCode

问题现象

整个调用链为hap ArkTS->har ArkTS->har Native侧->harArkTS。设定hap模块为entry。

  1. entry模块ArkTS调用har ArkTS侧A.ets页面导出的接口。
  2. har ArkTS侧A.ets页面中接口调用har Native侧的方法。
  3. har Native侧方法通过napi_load_module_with_info来加载har ArkTS侧B.ets导出的自定义接口。

har的ArkTS侧将函数包裹在命名空间中导出,其Native侧用napi_get_named_property加载函数,加载失败。

问题代码示例参考如下:


  1. // har包的ObjectUtil.ets
  2. namespace ObjectUtil {
  3. export function testOne() {
  4. console.info('你好,世界!')
  5. }
  6. }
  7. export { ObjectUtil }

  1. // har包的napi_init.cpp
  2. static napi_value loadModule(napi_env env, napi_callback_info info) {
  3. napi_value result;
  4. // 1.使用napi_load_module_with_info加载Test文件中的模块
  5. napi_status status = napi_load_module_with_info(env, "myTest_sdk/src/main/ets/common/ObjectUtil",
  6. "com.example.sodemo/myTest_sdk", &result);
  7. if (status != napi_ok) {
  8. return nullptr;
  9. }
  10. napi_value testFn;
  11. // 2.使用napi_get_named_property获取test函数
  12. status = napi_get_named_property(env, result, "testOne", &testFn); // 获取失败,status:napi_object_expected
  13. if (status != napi_ok) {
  14. return nullptr;
  15. }
  16. // 3.使用napi_call_function调用函数test
  17. status = napi_call_function(env, result, testFn, 0, nullptr, nullptr);
  18. if (status != napi_ok) {
  19. return nullptr;
  20. }
  21. return result;
  22. }

背景知识

应用开发中往往是由多个业务组共同完成一个APP的开发,每个业务组都有自己的工程,业务组会以HSP或har包的形式提供SDK能力给各个hap模块使用,这些SDK往往会提供C++接口或ets接口供其他模块直接调用。

Node-API中的napi_load_module_with_info接口的功能是进行模块的加载,当模块加载出来之后,可以使用函数napi_get_property获取模块导出的变量,也可以使用napi_get_named_property获取模块导出的函数。


  1. 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

加载的模块。

解决方案

  1. har的ArkTS侧导出接口时包裹了一层namespace,Native侧在加载时需要用napi_get_named_property()先获取到命名空间对象,再去获取函数对象(一共获取两次),无法直接获取函数。
  2. har是集成到hap中的,其入口模块是hap,即entry模块。napi_load_module_with_info中:
    • path:加载文件路径或者moduleName。注意此处的moduleName指的是入口模块(即entry模块)中oh-package.json5中dependencies标签下为har定义的名称,而不是har模块的实际名称。
      
          
      1. // hap(即entry模块)的oh-package.json5
      2. {
      3. "name": "entry",
      4. "version": "1.0.0",
      5. // ...
      6. "dependencies": {
      7. "lib_myTest_sdk": "file:../myTest_sdk"
      8. }
      9. }

      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中配置的名字。
      
          
      1. // hap(即entry模块)的module.json5
      2. {
      3. "module": {
      4. "name": "entry",
      5. "type": "entry",
      6. "description": "$string:module_desc",
      7. // ...
      8. }
      9. }

      module_info参数中的moduleName为入口模块的模块名entry,而非har的模块名myTest_sdk。module_info:com.example.sodemo/entry,非com.example.sodemo/myTest_sdk。

  3. 完整示例参考如下:
    
      
    1. // har包的napi_init.cpp
    2. static napi_value loadModule(napi_env env, napi_callback_info info) {
    3. napi_value result;
    4. // 1.使用napi_load_module_with_info加载Test文件中的模块
    5. napi_status status = napi_load_module_with_info(env, "lib_myTest_sdk/src/main/ets/common/ObjectUtil",
    6. "com.example.sodemo/entry", &result);
    7. if (status != napi_ok) {
    8. return nullptr;
    9. }
    10. napi_value testNamespace;
    11. napi_value testFn;
    12. // 2.使用napi_get_named_property获取命名空间对象
    13. status = napi_get_named_property(env, result, "ObjectUtil", &testNamespace);
    14. if (status != napi_ok) {
    15. return nullptr;
    16. }
    17. // 3.使用napi_get_named_property获取test函数
    18. status = napi_get_named_property(env, testNamespace, "testOne", &testFn);
    19. if (status != napi_ok) {
    20. return nullptr;
    21. }
    22. // 4.使用napi_call_function调用函数test
    23. status = napi_call_function(env, testNamespace, testFn, 0, nullptr, nullptr);
    24. if (status != napi_ok) {
    25. return nullptr;
    26. }
    27. return result;
    28. }
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐