Почему Ruby FFI не присоединяет функции из пользовательской библиотеки общих объектов

Я хотел бы загрузить пользовательскую функцию C ++ в Ruby 2.0, используя гем ffi. При загрузке моей пользовательской библиотеки в сеансе irb я получаю сообщение об ошибке во время вызова attach_function:

FFI::NotFoundError: Function 'add' not found in [/usr/local/lib/libbridge.so]

Вот как я создал и проверил свой общий объект libbridge:

Я получил заголовочный файл для моей библиотеки:

файл: bridge.h

std::string fooBar(std::string bar);
int add(int a, int b);

Реализация библиотек:

файл: bridge.cpp

#include <iostream>

std::string fooBar(std::string bar)
{
return "foo" + bar;
}

int add(int a, int b)
{
return a + b;
}

И код для двоичного файла, который я связываю с моей новой библиотекой:

файл: 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";
}

Сначала я компилирую свою библиотеку в объектный код:

$ 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 вместо этого не может видеть и монтировать эти функции.

Кто-нибудь может указать мне правильное направление здесь?

С уважением
Феликс

2

Решение

ffi ожидает функцию c, поэтому он не находит ваши функции c ++ из-за названия, которое искажает c ++.

Вы должны указать компоновщику сделать функции доступными из c, например, выполнив (в вашем .h) файле

extern "C" {
int add(int a, int b);
}

Я подозреваю, что FFI также не будет знать, что делать с функцией, которая ожидает std :: string в качестве аргумента

3

Другие решения

В OSX мне удалось скомпилировать с -dynamiclib:

g ++ -dynamiclib -o mylib.dylib mylib.cpp

0

По вопросам рекламы [email protected]