I'd like to load a custom C++ function inside Ruby 2.0 using the ffi gem. When loading my custom library in an irb session I get an error during the attach_function call:
FFI::NotFoundError: Function 'add' not found in [/usr/local/lib/libbridge.so]
Here's the way I created and checked my libbridge shared object:
I got a header file for my library:
file: bridge.h
std::string fooBar(std::string bar);
int add(int a, int b);
The libraries implementation:
file: bridge.cpp
#include <iostream>
std::string fooBar(std::string bar)
{
return "foo" + bar;
}
int add(int a, int b)
{
return a + b;
}
And the code for the binary that I link against my new library:
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";
}
First I compile my lib to object code:
$ g++ -c -Wall -Werror -fpic bridge.cpp
Then I make it a shared object:
$ g++ -shared -o libbridge.so bridge.o
I strip the debug symbols:
$ strip -o libbridge.so libbridge.so
And move it into my system:
$ sudo mv libbridge.so /usr/local/lib/
Then I make it executable and run ldconfig:
$ sudo chmod 0755 /usr/local/lib/libbridge.so
$ sudo ldconfig
Short check:
$ 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)
I remove the locale versions from my working dir:
$ rm -f bridge.so
$ rm -f bridge.o
And I compile my binary:
$ g++ -Wall -o bridger bridger.cpp -lbridge
I successfully execute it and get the output I expected:
$ ./bridger
foobarrrr
Adding 4 and 2: 6
Now I create a ruby module 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
When I load that code in an irb session now I always get this error:
$ 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>'
I do not understand, what the problem here is. My library obviously exports the :add and :fooBar functions, otherwise my bridger binary would not successfully link against this library. Ruby ffi instead is not able to see and mount these functions.
Can anyone point me into the right direction here?
Regards
Felix