我想使用ffi gem在Ruby 2.0中加载自定义C ++函数。在irb会话中加载我的自定义库时,我在attach_function调用期间收到错误:
FFI::NotFoundError: Function 'add' not found in [/usr/local/lib/libbridge.so]
这是我创建和检查libbridge共享对象的方式:
我的库有一个头文件:
file:bridge.h
std::string fooBar(std::string bar);
int add(int a, int b);
库实现:
file:bridge.cpp
#include <iostream>
std::string fooBar(std::string bar)
{
return "foo" + bar;
}
int add(int a, int b)
{
return a + b;
}
我链接到新库的二进制代码:
file:bridger.cpp
#include <iostream>
#include "bridge.h"
int main(int argc, char* argv[])
{
std::string foobar = fooBar("barrrr");
std::cout << foobar << "\n";
std::cout << "Adding 4 and 2: " << add(4,2) << "\n";
}
首先我将lib编译为目标代码:
$ g++ -c -Wall -Werror -fpic bridge.cpp
然后我把它变成一个共享对象:
$ g++ -shared -o libbridge.so bridge.o
我剥离调试符号:
$ strip -o libbridge.so libbridge.so
将其移入我的系统:
$ sudo mv libbridge.so /usr/local/lib/
然后我将其设为可执行文件并运行ldconfig:
$ sudo chmod 0755 /usr/local/lib/libbridge.so
$ sudo ldconfig
简短检查:
$ ldd /usr/local/lib/libbridge.so
linux-gate.so.1 => (0xb7781000)
libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb7689000)
libm.so.6 => /lib/i386-linux-gnu/i686/cmov/libm.so.6 (0xb7663000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xb7645000)
libc.so.6 => /lib/i386-linux-gnu/i686/cmov/libc.so.6 (0xb74e2000)
/lib/ld-linux.so.2 (0xb7782000)
我从工作目录中删除了语言环境版本:
$ rm -f bridge.so
$ rm -f bridge.o
我编译我的二进制文件:
$ g++ -Wall -o bridger bridger.cpp -lbridge
我成功执行它并获得我期望的输出:
$ ./bridger
foobarrrr
Adding 4 and 2: 6
现在我创建一个ruby模块ffi_test.rb:
require "ffi"
module FfiTest
extend FFI::Library
ffi_lib_flags :now, :global
ffi_lib "/usr/local/lib/libbridge.so"
attach_function :add, [:int, :int], :int
attach_function :fooBar, [:string], :string
end
当我在irb会话中加载该代码时,我总是会收到此错误:
$ irb
2.0.0p247 :001 > load "ffi_test.rb"
FFI::NotFoundError: Function 'add' not found in [/usr/local/lib/libbridge.so]
from /home/me/.rvm/gems/ruby-2.0.0-p247@global/gems/ffi-1.9.0/lib/ffi/library.rb:251:in `attach_function'
from ffi_test.rb:8:in `<module:EricInterface>'
from ffi_test.rb:3:in `<top (required)>'
from (irb):1:in `load'
from (irb):1
from /home/me/.rvm/rubies/ruby-2.0.0-p247/bin/irb:16:in `<main>'
我不明白,这里的问题是什么。我的库显然导出了:add和:fooBar函数,否则我的bridger二进制文件无法成功链接到这个库。 Ruby ffi无法查看和安装这些函数。
有人能指出我正确的方向吗?
此致 菲利克斯
答案 0 :(得分:3)
ffi期待一个c函数,所以它没有找到你的c ++函数,因为c ++的名称是错误的。
你需要告诉链接器使函数可以从c访问,例如通过(在你的.h)文件中进行访问
extern "C" {
int add(int a, int b);
}
我怀疑FFI也不会知道如何处理期望std :: string作为参数的函数
答案 1 :(得分:0)
在OSX上,对我有用的是用-dynamiclib编译:
g ++ -dynamiclib -o mylib.dylib mylib.cpp