You need to enable JavaScript to run this app. Ruby借助Fiddle加载C共享库时,如何正确加载项目内的依赖.so文件
优惠活动
大模型
产品
解决方案
定价
更多

Ruby借助Fiddle加载C共享库时,如何正确加载项目内的依赖.so文件

问题核心根因

根据你提供的strace跟踪结果,这个问题完全是第三方ServerApi.so的内部实现逻辑导致的:

  • 它没有走Linux系统动态链接器的标准依赖查找流程,而是自己调用readlink("/proc/self/exe")获取当前进程可执行文件的绝对路径
  • 拿到Ruby解释器的路径后,直接拼接同目录下的Network.so、Protobuf.so完整路径发起文件加载
  • 运行Ruby脚本时,/proc/self/exe指向的是Ruby解释器的安装目录(也就是报错里的.rvm/rubies/ruby-2.6.5/bin/路径),不是你存放项目文件的目录,自然会报文件找不到的错误

你之前把依赖库放到Ruby安装目录就能跑,本质上是刚好命中了这个库自己拼出来的查找路径,但这种方式会把项目文件散落到Ruby安装路径里,完全不符合项目集中管理的要求。

可落地的解决方法

方案1:提前预加载所有依赖(推荐,零额外配置)

Linux的glibc动态链接器有个原生机制:如果某个共享库已经被加载到当前进程的全局符号表,后续其他模块请求加载同名库时,会直接复用已有的内存句柄,不会重新去文件系统查找路径。
利用这个特性,只要在加载ServerApi.so之前,用项目目录下的绝对路径把所有依赖的.so提前加载到进程全局命名空间,就能跳过ServerApi.so内部的硬编码路径查找逻辑。
修改后的可用代码:

require 'fiddle'
require 'fiddle/import'

# 获取脚本所在目录的绝对路径,避免相对路径受进程工作目录变动影响
LIBS_DIR = File.expand_path(__dir__)
# 预加载底层依赖,显式指定全局可见的加载标记
Fiddle.dlopen(
  File.join(LIBS_DIR, 'Network.so'),
  Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL
)
Fiddle.dlopen(
  File.join(LIBS_DIR, 'Protobuf.so'),
  Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL
)

module Era
  extend Fiddle::Importer

  # 用绝对路径加载主库,替代原来的相对路径
  dlload File.join(LIBS_DIR, 'ServerApi.so')

  extern 'int era_init_lib()'
  extern 'void era_deinit_lib()'
  extern 'int era_process_request(const char* request, char** response)'
  extern 'void era_free(char* response)'
end

Era.era_init_lib
begin
  # 业务逻辑
ensure
  Era.era_deinit_lib
end

操作注意事项:

  • 所有.so的路径都要基于脚本位置转成绝对路径,不要用./这类相对路径,否则进程工作目录变动时依然会加载失败
  • 预加载顺序要符合依赖关系:先加载无其他依赖的底层库(Network、Protobuf),再加载上层的主库ServerApi
  • 预加载时一定要加RTLD_GLOBAL标记,确保库的符号对后续加载的ServerApi.so可见,否则会触发符号未定义的加载错误

方案2:通过LD_PRELOAD环境变量加载(适合不想改代码的场景)

如果不想改动现有Ruby脚本,可以在启动进程时,通过系统的LD_PRELOAD机制提前把依赖库加载到进程空间,效果和代码内预加载完全一致:

LD_PRELOAD="$PWD/Network.so:$PWD/Protobuf.so" ruby your_script.rb

这种方式不需要修改现有代码结构,只要启动时能正确定位到当前目录下的依赖库即可。


内容的提问来源于stack exchange,提问作者3limin4t0r

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.07 11:24:05