如何使用ruby ffi在ruby gem中调用自定义c代码

时间:2011-03-12 01:26:05

标签: ruby ffi

我想创建一个ruby gem来调用我编写的c函数。例如:

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

这将在我的rubygem中的c文件中。然后,我希望能够通过使用ffi接口包装它来在ruby中调用它:

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

但是我不知道如何设置它,所以当安装gem时,c文件将编译成一个库(名称为'MyLib'),ffi将检测库并在其中使用它上面的代码。

有谁知道如何做到这一点,还是有更好的方法来解决这个问题?请注意,我宁愿不使用扩展ruby的标准方法(如Pragmatic Programmer's Guide Extending Ruby section中所述),因为这只适用于标准的ruby解释器(我相信)。

我一直在使用jeweler来构建我的宝石,如果这对这个问题很重要。

1 个答案:

答案 0 :(得分:4)

nanothief,首先你必须咨询你的C编译器,将你的C代码编译成一个库。

例如,假设上面的函数位于名为MyLib.c的文件中,并假设您使用GCC:

$ gcc -c MyLib.c

...导致MyLib.o目标文件

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

...这导致MyLib.so共享对象,这是您的库文件(但请记住,虽然这个库可能在我的环境中编译正常,但在您的环境中可能对您不起作用)。< / p>

然后,在您的Ruby代码中,您需要使用以下命令加载FFI gem:

require 'ffi'

然而,使用FFI / Ruby方法的好处在于您不需要对您的gem用户环境做出假设。因此,在大多数情况下,您使用ffi_lib加载的库应该已经编译并存在于gem用户计算机的库路径上的某个位置。

使用C扩展,您必须使用gem打包C源并让gem用户自己编译C源。如果您的用户无法访问其环境的C编译器,或者他们使用的是JRuby(仅限于对C扩展,IIRC的支持),则这可能不起作用。

如果您有兴趣,可以查看此gem I wrote that leverages FFI