我正在尝试使用Fiddle在 Ruby 中加载 C 共享库。
这是一个最小的例子:
require 'fiddle'
require 'fiddle/import'
module Era
extend Fiddle::Importer
dlload './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
共享库加载没有问题。但是,当我调用Era.era_init_lib
它时,它会尝试加载其他库(Network.so
和Protobuf.so
)。我有这些文件位于当前工作目录(在同一目录中ServerApi.so
)。
但是,当我尝试执行上面的代码时,我收到以下错误:
! Failed to load library: /home/username/.rvm/rubies/ruby-2.6.5/bin/Network.so, error: /home/username/.rvm/rubies/ruby-2.6.5/bin/Network.so: cannot open shared object file: No such file or directory
如果我将文件放在该位置,则错误描述一切正常。
我的猜测是 fiddle 的 C 工作目录与 Ruby 工作目录不同。我想将项目文件保留在项目中,而不是 Ruby 安装目录中。
如何Network.so
从我的项目文件夹中使用?
所有*.so
文件均由第三方提供。我没有源代码,因此无法更改这些文件。函数签名由文档提供。
Network.so
在中搜索strace
给了我这些结果:
readlink("/proc/self/exe", "/home/username/.rvm/rubies/ruby-2."..., 4096) = 44
openat(AT_FDCWD, "/home/username/.rvm/rubies/ruby-2.6.5/bin/Network.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
futex(0x7fcc16666d90, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7fcc16b44520, FUTEX_WAKE_PRIVATE, 2147483647) = 0
write(2, "! Failed to load library: ", 26! Failed to load library: ) = 26
write(2, "/home/username/.rvm/rubies/ruby-2."..., 50/home/username/.rvm/rubies/ruby-2.6.5/bin/Network.so) = 50
write(2, ", error: ", 9, error: ) = 9
write(2, "/home/username/.rvm/rubies/ruby-2."..., 109/home/username/.rvm/rubies/ruby-2.6.5/bin/Network.so: cannot open shared object file: No such file or directory) = 109
write(2, "\n", 1) = 1
我还编写了一个 C 脚本,它执行相同的操作,当文件被放入同一目录时,它工作得非常好。所以这可能是库的错误,我假设它会检查当前正在运行的程序的位置,然后尝试从该文件夹加载库。这将解释作为 Ruby 脚本运行时的行为(因为它作为 Ruby 程序的一部分运行),而 C 二进制文件独立运行。
对于那些想要重新创建(Linux)问题的人。您可以从这里下载必要的文件。这给了你server-linux-x86_64.sh
文件。
支持的发行版有:Suse、Ubuntu、Debian、Red Hat 和 CentOS,但其他发行版也可以正常工作。
您可以运行安装程序,它将文件放在/opt/eset/RemoteAdministrator/Server
. 或者,假设大多数人不想安装完整的应用程序,您可以运行以下命令:
sed '1,/^# Start of TAR\.GZ file #$/d' server-linux-x86_64.sh | sed '1d' > server-linux-x86_64.tar.gz
这会从 .sh 文件中删除所有安装程序说明,只留下二进制 .tar.gz 数据,将其写入server-linux-x86_64.tar.gz
.
将文件复制到您喜欢的目录中ServerApi.so
。在同一目录中创建一个 Ruby 脚本(带有问题代码)并运行该脚本。Protobuf.so
Network.so