如何使用napi_load_module_with_info接口加载不同类型的模块(如本地工程模块、远程包、API模块、Native库等)?

如题:如何使用napi_load_module_with_info接口加载不同类型的模块(如本地工程模块、远程包、API模块、Native库等)?

本文参与了 【 HarmonyOS NEXT 技术问答冲榜,等你来战!】欢迎正在阅读的你也加入。

阅读 562
avatarAI BotBETA

回答

napi_load_module_with_info 是 Node.js 原生插件(N-API)用于加载原生模块(Native Module)的接口。它主要用于加载编译后的本地 .node 文件(即原生库)。然而,对于不同类型的模块(如本地工程模块、远程包、API模块等),napi_load_module_with_info 的使用方式和适用性有所不同:

  1. 本地工程模块

    • 如果本地工程模块已经被编译为 .node 文件,你可以直接使用 napi_load_module_with_info 来加载它。
    • 通常,你需要确保 .node 文件的路径正确,并传递给 napi_load_module_with_info
  2. 远程包

    • napi_load_module_with_info 不能直接加载远程包。远程包通常需要先下载到本地,然后编译(如果需要),最后才能使用 napi_load_module_with_info 或其他机制加载。
    • 你可以使用 Node.js 的包管理工具(如 npm 或 yarn)来下载和编译远程包。
  3. API 模块

    • 如果“API 模块”指的是纯 JavaScript 或 TypeScript 编写的模块,那么它们不需要通过 napi_load_module_with_info 来加载。
    • 这些模块可以通过 Node.js 的 requireimport 语句来加载。
  4. Native 库

    • napi_load_module_with_info 专门用于加载编译后的 Native 库(.node 文件)。
    • 你需要确保 .node 文件与你的 Node.js 版本和架构兼容。

示例代码

以下是一个使用 napi_load_module_with_info 加载本地 .node 文件的简单示例:

#include <node_api.h>
#include <stdio.h>

napi_value Init(napi_env env, napi_value exports) {
    napi_value fn;
    napi_status status;

    // 指定 .node 文件的路径(这里假设文件名为 "mymodule.node")
    const char* path = "./mymodule.node";

    // 加载模块
    napi_handle_scope scope;
    status = napi_open_handle_scope(env, &scope);
    if (status != napi_ok) {
        napi_throw_error(env, NULL, "Failed to open handle scope");
        return NULL;
    }

    napi_module module;
    status = napi_load_module_with_info(env, path, &module, NULL, NULL);
    if (status != napi_ok) {
        napi_throw_error(env, NULL, "Failed to load module");
        napi_close_handle_scope(env, scope);
        return NULL;
    }

    // 假设模块导出了一个名为 "hello" 的函数
    napi_value hello_fn;
    status = napi_get_named_property(env, module.module, "hello", &hello_fn);
    if (status != napi_ok || !napi_is_function(env, hello_fn)) {
        napi_throw_error(env, NULL, "Module does not export a 'hello' function");
        napi_close_handle_scope(env, scope);
        return NULL;
    }

    // 将函数导出给 JavaScript
    status = napi_set_named_property(env, exports, "helloFromNative", hello_fn);
    if (status != napi_ok) {
        napi_throw_error(env, NULL, "Failed to set export property");
        napi_close_handle_scope(env, scope);
        return NULL;
    }

    napi_close_handle_scope(env, scope);
    return exports;
}

NAPI_MODULE_INIT() {
    return Init(env, exports);
}

在这个示例中,napi_load_module_with_info 被用来加载一个名为 mymodule.node 的原生模块,并从中提取一个名为 hello 的函数,然后将其导出给 JavaScript 使用。

总结

  • napi_load_module_with_info 主要用于加载本地编译后的 .node 文件(Native 库)。
  • 对于其他类型的模块(如远程包、API 模块),需要使用不同的方法来加载和处理。
1 个回答
  • 加载本地工程模块(HAP加载模块内文件路径):

    1. 在工程的build - profile.json5文件中,将模块文件路径添加到arkOptions.runtimeOnly.sources数组中。
    2. 在C++代码中,调用napi_load_module_with_info,传入当前虚拟机环境(env)、模块相对路径(以moduleName开头,如"entry/src/main/ets/Test")、bundleName/moduleName(如"com.example.application/entry")和用于存储加载结果的变量地址。
    3. 使用napi_get_named_property获取模块中的函数,napi_call_function调用函数,napi_get_property获取变量。
    • 加载本地工程模块(HAP加载HAR模块名):

      1. oh - package.json5文件中配置dependencies项指定HAR模块依赖。
      2. build - profile.json5文件中,将HAR模块名添加到arkOptions.runtimeOnly.packages数组中。
      3. 在C++代码中,调用napi_load_module_with_info,传入环境、HAR模块名(如"library")、bundleName/moduleName和结果变量地址,后续获取函数和变量的操作与加载模块内文件路径类似。
    • 加载远程包(HAP加载远程HAR模块名或ohpm包名):

      1. oh - package.json5文件中配置dependencies项指定远程包依赖(如"@ohos/hypium": "1.0.16""json5": "^2.2.3")。
      2. build - profile.json5文件中,将远程包名添加到arkOptions.runtimeOnly.packages数组中。
      3. 在C++代码中,调用napi_load_module_with_info,传入环境、远程包名(如"@ohos/hypium""json5")、bundleName/moduleName和结果变量地址,然后根据需要获取模块中的变量或函数并进行操作。
    • 加载API模块(如@ohos.hilog):

      1. 在C++代码中,调用napi_load_module_with_info,传入环境、API模块名(如"@ohos.hilog")、nullptr(因为API模块不需要bundleName/moduleName)和结果变量地址。
      2. 使用napi_get_named_property获取API模块中的函数(如info函数),创建参数并使用napi_call_function调用函数。
    • 加载Native库(如libentry.so):

      1. oh - package.json5文件中配置dependencies项指定Native库依赖(如"libentry.so": "file:../src/main/cpp/types/libentry")。
      2. build - profile.json5文件中,将Native库名添加到arkOptions.runtimeOnly.packages数组中。
      3. 在C++代码中,调用napi_load_module_with_info,传入环境、Native库名(如"libentry.so")、bundleName/moduleName和结果变量地址,使用napi_get_named_property获取Native库中的函数(如add函数),创建参数并使用napi_call_function调用函数。

本文参与了 【 HarmonyOS NEXT 技术问答冲榜,等你来战!】欢迎正在阅读的你也加入。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进