Как использовать ruby ​​ffi для вызова пользовательского кода c в геме ruby - PullRequest
2 голосов
/ 12 марта 2011

Я хочу создать рубиновый гем, который вызывает функцию c, которую я написал. Например:

int func(int x)
{
  return x * 2;
}

Это было бы в файле c в моем rubygem. Затем я хотел бы иметь возможность вызывать его в ruby, обернув его интерфейсом ffi:

  module TestModule
    extend FFI::Library
    ffi_lib 'MyLib'
    attach_function 'func', [:int], :int
  end

Однако я не уверен, как это настроить, чтобы при установке gem файл c скомпилировался в библиотеку (с именем «MyLib»), и ffi обнаружит библиотеку и использует ее в код выше.

Кто-нибудь знает, как это сделать, или есть лучший способ сделать это? Обратите внимание, что я бы предпочел не использовать стандартный способ расширения ruby ​​(как описано в разделе Прагматическое руководство программиста по расширению Ruby ), поскольку он будет работать только со стандартным интерпретатором ruby ​​(я полагаю).

Я использовал ювелир для изготовления своих драгоценных камней, если это имеет значение для этого вопроса.

1 Ответ

4 голосов
/ 08 апреля 2011

nanothief, сначала вы должны проконсультироваться со своим компилятором C, чтобы скомпилировать ваш код C в библиотеку.

Например, если предположить, что указанная выше функция находится в файле с именем MyLib.c, и предполагается, что вы используете GCC:

$ gcc -c MyLib.c

... что приводит к объектному файлу MyLib.o

$ gcc -shared -o MyLib.so MyLib.o

... что приводит к общему объекту MyLib.so, который является файлом вашей библиотеки (но имейте в виду, что хотя эта библиотека может хорошо скомпилироваться для меня в моей среде, она может не работать для вас в вашей среде).

Затем в вашем коде Ruby вам необходимо загрузить гем FFI с помощью:

require 'ffi'

Тем не менее, прелесть использования подхода FFI / Ruby заключается в том, что вам не нужно делать предположения о среде ваших пользователей драгоценных камней. Следовательно, в большинстве случаев ожидается, что библиотека, которую вы загружаете с помощью ffi_lib, уже скомпилирована и существует где-то на пути к библиотеке вашего компьютера пользователя gem.

С расширением C вы должны будете упаковать источник C вместе с вашим драгоценным камнем, и ваши пользователи будут сами компилировать источник C. Это может не работать, если ваши пользователи не имеют доступа к компилятору C для своей среды или если они используют JRuby (имеет ограниченную поддержку расширений C, IIRC).

Если вам интересно, вы можете взглянуть на этот камень, который я написал, который использует FFI .

...