Erlang load_nif/2在项目导入后无法找到共享库问题求助
问题概述
某Elixir应用通过NIF调用C++代码,原项目运行正常,但集成到其他项目后出现加载错误:
Failed to load NIF library: '<relative_path_to_lib>/<lib_name>.so: cannot open shared object file: No such file or directory'
已尝试调整.so文件位置、使用绝对路径等操作,均未解决。关键现象为:编译后首次测试正常,重复运行测试时出错;同一测试内重复调用函数无问题,仅跨测试运行时触发错误。
系统环境:
- Ubuntu 22.04
- Elixir 1.13.0(基于Erlang/OTP 24编译)
原因分析与解决方法
1. 相对路径基准偏移
当应用作为依赖集成到主项目后,测试运行时的工作目录可能切换为主项目根目录,导致原有的相对路径指向错误。即使首次测试时路径有效,后续测试可能因工作目录变化失效。
解决办法:使用Application.app_dir/1获取应用的安装目录,拼接出绝对路径加载NIF,确保路径始终指向依赖项目中的共享库:
def load_nifs do # 替换:your_app_name为你的依赖应用名,priv/lib为.so文件实际存放路径 lib_path = Application.app_dir(:your_app_name, "priv/lib/<lib_name>") :erlang.load_nif(lib_path, 0) :ok end
2. 测试运行时路径验证
可以在加载代码中添加调试输出,确认工作目录和文件状态,定位路径问题:
def load_nifs do target_path = "<relative_path_to_lib>/<lib_name>" IO.inspect(File.cwd!(), label: "Current Working Directory") IO.inspect(File.exists?(target_path), label: "Library File Exists") IO.inspect(File.readable?(target_path), label: "Library File Readable") :erlang.load_nif(target_path, 0) :ok end
运行测试时查看输出,就能明确是路径指向错误还是文件权限问题。
3. 动态链接库依赖缺失
部分情况下,系统提示“找不到文件”实际是因为.so文件依赖的其他共享库缺失,而非目标文件本身不存在。
解决办法:使用ldd命令检查目标.so文件的依赖情况:
ldd /path/to/your/lib_name.so
若输出中存在not found的条目,需安装对应依赖库,或通过LD_LIBRARY_PATH环境变量指定依赖库路径。
4. 依赖项目的NIF编译配置问题
主项目构建时,若依赖项目的NIF未正确编译生成.so文件,也会导致后续测试时文件缺失。
解决办法:确认依赖项目的mix.exs中正确配置了NIF编译规则:
def project do [ # 启用elixir_make编译器 compilers: [:elixir_make | Mix.compilers()], # 配置elixir_make的编译目标 elixir_make: [make_args: ["all"]] ] end
确保主项目执行mix deps.get和mix compile时,会自动编译C++代码生成.so文件。
内容的提问来源于stack exchange,提问作者TheLastEngineer

