使用Node-API接口在主线程中进行模块加载
=======================

#### 场景介绍

Node-API中的napi\_load\_module接口的功能是在主线程中进行模块的加载，当模块加载出来之后，可以使用函数napi\_get\_property获取模块导出的变量，也可以使用napi\_get\_named\_property获取模块导出的函数。

#### 函数说明

napi\_status napi\_load\_module(napi\_env env, const char\* path, napi\_value\* result);

| 参数 | 说明 |
| :-- | :-- |
| env | 当前的虚拟机环境 |
| path | 加载的文件路径或者模块名 |
| result | 加载的模块 |

#### 使用限制

*   禁止在非主线程当中使用该接口。
*   禁止在Init函数中使用该接口。
*   禁止在线程安全函数的回调函数当中进行文件路径的加载。
*   在信号函数中调用不安全，直接调用可能导致栈溢出。

建议使用[napi\_load\_module\_with\_info](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/use-napi-load-module-with-info)来进行模块加载，该接口支持了更多的场景。

#### napi\_load\_module支持的场景

| 场景 | 详细分类 | 说明 |
| :-- | :-- | :-- |
| 系统模块 | 加载@ohos.或 @system. | \- |
| 本地工程模块 | 加载ets目录下文件中的模块 | 要求路径以ets开头 |
| 本地工程模块 | 加载模块内文件路径 | 要求路径以moduleName开头 |
| 本地工程模块 | 加载HAR模块名 | \- |
| 本地工程模块 | 加载HSP模块名 | \- |
| 远程包 | 加载远程HAR模块名 | \- |
| 远程包 | 加载ohpm包名 | \- |
| 模块Native库 | 加载Native模块(.so文件) | \- |

*   **加载系统模块**
    
    static napi\_value loadModule(napi\_env env, napi\_callback\_info info)
    {
        // 1. 使用napi\_load\_module加载模块@ohos.hilog
        napi\_value result;
        napi\_status status = napi\_load\_module(env, "@ohos.hilog", &result);
        if (status != napi\_ok) {
            return nullptr;
        }
    
        // 2. 使用napi\_get\_named\_property获取info函数
        napi\_value infoFn;
        status = napi\_get\_named\_property(env, result, "info", &infoFn);
        if (status != napi\_ok) {
            return nullptr;
        }
    
        napi\_value tag;
        std::string formatStr = "test";
        napi\_create\_string\_utf8(env, formatStr.c\_str(), formatStr.size(), &tag);
    
        napi\_value outputString;
        std::string str = "Hello HarmonyOS";
        napi\_create\_string\_utf8(env, str.c\_str(), str.size(), &outputString);
    
        napi\_value flag;
        napi\_create\_int32(env, 0, &flag);
    
        napi\_value args\[3\] = {flag, tag, outputString};
        // 3. 使用napi\_call\_function调用info函数
        status = napi\_call\_function(env, result, infoFn, 3, args, nullptr);
        if (status != napi\_ok) {
            return nullptr;
        }
        return result;
    }
    
*   **加载ets目录下文件中的模块**
    
    当加载文件中的模块时，如以下ArkTS代码：
    
    let value = 123;
    function test() {
      console.info('Hello HarmonyOS');
    }
    export {value, test};
    

1.  需要在模块的build-profile.json5文件中进行以下配置：
    
    "buildOption": {
      "arkOptions" : {
        "runtimeOnly" : {
          "sources": \[
            "./src/main/ets/Test.ets"
          \],
          "packages": \[
            "library",
            "sharedlibrary",
            "@ohos/hypium",
            "@ohos/axios",
            "libentry7.so"
          \]
        }
      },
    
2.  使用napi\_load\_module加载Test文件，调用函数test以及获取变量value：
    
    static napi\_value loadModule(napi\_env env, napi\_callback\_info info)
    {
        napi\_value result;
        // 1. 使用napi\_load\_module加载Test文件中的模块
        napi\_status status = napi\_load\_module(env, "ets/Test", &result);
        if (status != napi\_ok) {
            return nullptr;
        }
    
        napi\_value testFn;
        // 2. 使用napi\_get\_named\_property获取test函数
        status = napi\_get\_named\_property(env, result, "test", &testFn);
        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;
        }
    
        napi\_value value;
        napi\_value key;
        std::string keyStr = "value";
        napi\_create\_string\_utf8(env, keyStr.c\_str(), keyStr.size(), &key);
        // 4. 使用napi\_get\_property获取变量value
        status = napi\_get\_property(env, result, key, &value);
        if (status != napi\_ok) {
            return nullptr;
        }
        return result;
    }
    

*   **加载模块内文件路径**
    
    当加载文件中的模块时，如以下ArkTS代码：
    
    //./src/main/ets/Test.ets
    let value = 123;
    function test() {
      console.info("Hello HarmonyOS");
    }
    export {value, test};
    

1.  需要当前模块的build-profile.json5文件中进行以下配置：
    
    {
      "buildOption" : {
        "arkOptions" : {
          "runtimeOnly" : {
            "sources": \[
              "./src/main/ets/Test.ets"
            \]
          }
        }
      }
    }
    
2.  使用napi\_load\_module加载Test文件，调用函数test以及获取变量value：
    
    static napi\_value loadModule(napi\_env env, napi\_callback\_info info) {
        napi\_value result;
        // 1. 使用napi\_load\_module加载Test文件中的模块
        napi\_status status = napi\_load\_module(env, "entry/src/main/ets/Test", &result);
        if (status != napi\_ok) {
            return nullptr;
        }
    
        napi\_value testFn;
        // 2. 使用napi\_get\_named\_property获取test函数
        status = napi\_get\_named\_property(env, result, "test", &testFn);
        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;
        }
    
        napi\_value value;
        napi\_value key;
        std::string keyStr = "value";
        napi\_create\_string\_utf8(env, keyStr.c\_str(), keyStr.size(), &key);
        // 4. 使用napi\_get\_property获取变量value
        status = napi\_get\_property(env, result, key, &value);
        if (status != napi\_ok) {
            return nullptr;
        }
        return result;
    }
    

*   **加载HAR模块名**
    
    HAR包Index.ets文件如下：
    
    //library Index.ets
    let value = 123;
    function test() {
      console.info("Hello HarmonyOS");
    }
    export {value, test};
    

1.  在当前模块下的oh-package.json5文件中配置dependencies项：
    
    {
      "dependencies": {
        "library": "file:../library"
      }
    }
    
2.  在使用library的模块中，对build-profile.json5进行配置：
    
    {
      "buildOption" : {
        "arkOptions" : {
          "runtimeOnly" : {
            "packages": \[
              "library"
            \]
          }
        }
      }
    }
    
3.  用napi\_load\_module加载library，调用函数test以及获取变量value：
    
    static napi\_value loadModule(napi\_env env, napi\_callback\_info info) {
        napi\_value result;
        // 1. 使用napi\_load\_module加载library
        napi\_status status = napi\_load\_module(env, "library", &result);
        if (status != napi\_ok) {
            return nullptr;
        }
    
        napi\_value testFn;
        // 2. 使用napi\_get\_named\_property获取test函数
        status = napi\_get\_named\_property(env, result, "test", &testFn);
        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;
        }
    
        napi\_value value;
        napi\_value key;
        std::string keyStr = "value";
        napi\_create\_string\_utf8(env, keyStr.c\_str(), keyStr.size(), &key);
        // 4. 使用napi\_get\_property获取变量value
        status = napi\_get\_property(env, result, key, &value);
        if (status != napi\_ok) {
            return nullptr;
        }
        return result;
    }
    

*   **加载HSP模块名**
    
    HSP包Index.ets文件如下：
    
    //sharedlibrary Index.ets
    let value = 123;
    function test() {
      console.info("Hello HarmonyOS");
    }
    export {value, test};
    

1.  在当前模块下的oh-package.json5文件中配置dependencies项：
    
    {
      "dependencies": {
        "sharedlibrary": "file:../sharedlibrary"
      }
    }
    
2.  在使用library的模块中，对build-profile.json5进行配置：
    
    {
      "buildOption" : {
        "arkOptions" : {
          "runtimeOnly" : {
            "packages": \[
              "sharedlibrary"
            \]
          }
        }
      }
    }
    
3.  用napi\_load\_module加载sharedlibrary，调用函数test以及获取变量value：
    
    static napi\_value loadModule(napi\_env env, napi\_callback\_info info) {
        napi\_value result;
        // 1. 使用napi\_load\_module加载sharedlibrary
        napi\_status status = napi\_load\_module(env, "sharedlibrary", &result);
        if (status != napi\_ok) {
            return nullptr;
        }
    
        napi\_value testFn;
        // 2. 使用napi\_get\_named\_property获取test函数
        status = napi\_get\_named\_property(env, result, "test", &testFn);
        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;
        }
    
        napi\_value value;
        napi\_value key;
        std::string keyStr = "value";
        napi\_create\_string\_utf8(env, keyStr.c\_str(), keyStr.size(), &key);
        // 4. 使用napi\_get\_property获取变量value
        status = napi\_get\_property(env, result, key, &value);
        if (status != napi\_ok) {
            return nullptr;
        }
        return result;
    }
    

*   **加载远程HAR模块名**

1.  在当前模块下的oh-package.json5文件中配置dependencies项：
    
    {
      "dependencies": {
        "@ohos/hypium": "1.0.16"
      }
    }
    
2.  在使用@ohos/hypium的模块中，对build-profile.json5进行配置：
    
    {
      "buildOption" : {
        "arkOptions" : {
          "runtimeOnly" : {
            "packages": \[
              "@ohos/hypium"
            \]
          }
        }
      }
    }
    
3.  用napi\_load\_module加载@ohos/hypium，获取DEFAULT变量：
    
    static napi\_value loadModule(napi\_env env, napi\_callback\_info info) {
        napi\_value result;
        // 1. 使用napi\_load\_module加载@ohos/hypium
        napi\_status status = napi\_load\_module(env, "@ohos/hypium", &result);
        if (status != napi\_ok) {
            return nullptr;
        }
    
        napi\_value key;
        std::string keyStr = "DEFAULT";
        napi\_create\_string\_utf8(env, keyStr.c\_str(), keyStr.size(), &key);
        // 2. 使用napi\_get\_property获取DEFAULT变量
        napi\_value defaultValue;
        status = napi\_get\_property(env, result, key, &defaultValue);
        if (status != napi\_ok) {
            return nullptr;
        }
        return result;
    }
    

*   **加载ohpm包名**

1.  在当前模块下的oh-package.json5文件中配置dependencies项：
    
    {
      "dependencies": {
        "@ohos/axios": "2.2.4",
      }
    }
    
2.  在使用@ohos/axios的模块中，对build-profile.json5进行配置：
    
    {
      "buildOption" : {
        "arkOptions" : {
          "runtimeOnly" : {
            "packages": \[
              "@ohos/axios"
            \]
          }
        }
      }
    }
    
3.  用napi\_load\_module加载@ohos/axios，获取VERSION变量：
    
    static napi\_value loadModule(napi\_env env, napi\_callback\_info info) {
        napi\_value result;
        // 1. 使用napi\_load\_module加载@ohos/axios
        napi\_status status = napi\_load\_module(env, "@ohos/axios", &result);
        if (status != napi\_ok) {
            return nullptr;
        }
    
        napi\_value key;
        std::string keyStr = "VERSION";
        napi\_create\_string\_utf8(env, keyStr.c\_str(), keyStr.size(), &key);
        // 2. 使用napi\_get\_property获取VERSION
        napi\_value defaultValue;
        status = napi\_get\_property(env, result, key, &defaultValue);
        if (status != napi\_ok) {
            return nullptr;
        }
        return result;
    }
    

*   **加载Native库**
    
    libentry.so的index.d.ts文件如下：
    
    //index.d.ts
    export const add: (a: number, b: number) => number;
    

1.  在当前模块下的oh-package.json5文件中配置dependencies项：
    
    {
      "dependencies": {
        "libentry.so": "file:../src/main/cpp/types/libentry"
      }
    }
    
2.  在使用libentry.so的模块中，对build-profile.json5进行配置：
    
    {
      "buildOption" : {
        "arkOptions" : {
          "runtimeOnly" : {
            "packages": \[
              "libentry.so"
            \]
          }
        }
      }
    }
    
3.  用napi\_load\_module加载libentry.so，调用函数add：
    
    static napi\_value loadModule(napi\_env env, napi\_callback\_info info) {
        napi\_value result;
        // 1. 使用napi\_load\_module加载libentry.so
        napi\_status status = napi\_load\_module(env, "libentry.so", &result);
        if (status != napi\_ok) {
            return nullptr;
        }
    
        napi\_value addFn;
        // 2. 使用napi\_get\_named\_property获取add函数
        status = napi\_get\_named\_property(env, result, "add", &addFn);
        if (status != napi\_ok) {
            return nullptr;
        }
        
        napi\_value a;
        napi\_value b;
        napi\_create\_int32(env, 2, &a);
        napi\_create\_int32(env, 3, &b);
        napi\_value args\[2\] = {a, b};
        // 3. 使用napi\_call\_function调用函数add
        napi\_value returnValue;
        status = napi\_call\_function(env, result, addFn, 2, args, &returnValue);
        if (status != napi\_ok) {
            return nullptr;
        }
        return result;
    }
    

*   **HAR加载HAR模块名**
    
    场景为har1加载har2，har2中的Index.ets文件如下：
    
    //har2 Index.ets
    let value = 123;
    function test() {
      console.info("Hello HarmonyOS");
    }
    export {value, test};
    

1.  在har1中的oh-package.json5文件中配置dependencies项：
    
    {
      "dependencies": {
        "har2": "file:../har2"
      }
    }
    
2.  在har1的build-profile.json5文件中进行配置：
    
    {
      "buildOption" : {
        "arkOptions" : {
          "runtimeOnly" : {
            "packages": \[
              "har2"
            \]
          }
        }
      }
    }
    
3.  在har1中用napi\_load\_module加载har2，调用函数test以及获取变量value：
    
    static napi\_value loadModule(napi\_env env, napi\_callback\_info info) {
        napi\_value result;
        // 1. 使用napi\_load\_module加载har2
        napi\_status status = napi\_load\_module(env, "har2", &result);
        if (status != napi\_ok) {
            return nullptr;
        }
        
        napi\_value testFn;
        // 2. 使用napi\_get\_named\_property获取test函数
        status = napi\_get\_named\_property(env, result, "test", &testFn);
        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;
        }
    
        napi\_value value;
        napi\_value key;
        std::string keyStr = "value";
        napi\_create\_string\_utf8(env, keyStr.c\_str(), keyStr.size(), &key);
        // 4. 使用napi\_get\_property获取变量value
        status = napi\_get\_property(env, result, key, &value);
        if (status != napi\_ok) {
            return nullptr;
        }
        return result;
    }