1. “Module Not Found”

在鸿蒙应用中,我们使用C++编写了核心逻辑,并通过NAPI暴露给ArkTS。
构建成功,安装成功。
但在运行 import testNapi from '@ohos.library.name' 时,程序直接崩溃或报错:
Error: module not found 或者 Error: dynamic library load failed.

2. 模块注册机制解析

鸿蒙的Native模块加载依赖于 libentry.so(或者其他名字)中的特定符号 napi_register_module_v1
ArkTS引擎在加载so文件时,会查找这个构造函数并执行注册。

注册流程图

Look for
dlopen
dlsym
Define
Return
import xxx
libxxx.so
System
napi_register_module_v1
Properties & Functions
JS Object

3. 常见错误一:SO命名不匹配

oh-package.json5build-profile.json5 中,你定义了模块名称。
但在 CMakeLists.txt 中,生成的库名字必须匹配。

检查点:

  1. CMakeLists.txt:

    add_library(entry SHARED ...) 
    # 生成的是 libentry.so
    
  2. ArkTS 导入路径:
    如果你的库叫 entry,导入通常是 libentry.so 对应的模块名。

4. 常见错误二:nm_modname 不一致

在C++代码中,注册结构体的 nm_modname 字段非常关键。它必须与模块名一致(或者匹配导入时的预期)。

static napi_module _module = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init, // 初始化函数
    .nm_modname = "entry",    // ⚠️ 必须与库名或模块名一致!
    .nm_priv = ((void *)0),
    .reserved = {0}
};

extern "C" __attribute__((constructor)) void RegisterModule(void) {
    napi_module_register(&_module);
}

如果 nm_modname 写成了 “demo”,而你加载的是 “entry”,可能会导致注册未能正确挂载。

5. 常见错误三:大小写敏感与路径

鸿蒙文件系统是大小写敏感的。
libEntry.solibentry.so 是两个文件。
确保 CMakeLists.txt 中的 add_library 名称全部小写(推荐),以避免不必要的麻烦。

6. 实战技巧:手动加载调试

如果自动导入失败,我们可以尝试在代码中打印日志,确认 RegisterModule 是否被调用。
这是一个 __attribute__((constructor)) 函数,在so加载时应该立即执行。

如果在日志(HiLog)中没看到打印,说明so文件根本没被加载
原因可能是:

  1. so文件没打包进HAP。检查 build/default/intermediates/.../libs 目录。
  2. 依赖缺失。如果你的 libentry.so 依赖 libQt6Core.so,而 libQt6Core.so 没在路径下,dlopen 会失败。

解决依赖问题:
确保所有依赖的Qt库都已包含在HAP的 libs/arm64-v8a 目录下。

7. 总结

模块注册失败通常是细节魔鬼:

  1. 名字:CMake Target名 = SO文件名 = nm_modname = import名。保持这四者一致(例如都叫 myapilib)。
  2. 依赖:使用 readelf -d libentry.so 查看依赖项,确保所有依赖都在设备上存在。
  3. 版本:NAPI版本兼容性(通常不是大问题,除非用了极新特性)。

排查时,先看HiLog有没有 “dlopen failed”,再看有没有进入 C++ 的 RegisterModule

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐