我想创建一个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来构建我的宝石,如果这对这个问题很重要。
答案 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。