【问题标题】:How to use ruby ffi for calling custom c code in a ruby gem如何使用 ruby​​ ffi 在 ruby​​ gem 中调用自定义 c 代码
【发布时间】:2011-03-12 01:26:04
【问题描述】:

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

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

这将在我的 ruby​​gem 的 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 来构建我的宝石,如果这对这个问题很重要的话。

【问题讨论】:

    标签: ruby ffi


    【解决方案1】:

    nanothief,首先您必须咨询您的 C 编译器才能将您的 C 代码编译到库中。

    例如,假设上面的函数在一个名为 MyLib.c 的文件中,并且假设你使用 GCC:

    $ gcc -c MyLib.c
    

    ... 生成 MyLib.o 目标文件

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

    ... 这会导致 MyLib.so 共享对象,这是您的库文件(但请记住,虽然此库在我的环境中可能对我来说编译得很好,但在您的环境中可能不适合您)。

    然后,在您的 Ruby 代码中,您需要加载 FFI gem:

    require 'ffi'
    

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

    使用 C 扩展,您必须将 C 源代码与您的 gem 一起打包,并让您的 gem 用户自己编译 C 源代码。如果您的用户无法访问其环境的 C 编译器,或者如果他们正在使用 JRuby(仅对 C 扩展,IIRC 提供有限支持),这可能不起作用。

    如果你有兴趣,可以看看这个gem I wrote that leverages FFI

    【讨论】:

    • 我想我误解了使用 ffi 的好处。我的库正在调用我已经编写的一些 c 代码,我想使用该代码而不是为代码中使用的所有函数编写 ffi 接口并用 ruby​​ 重写它。但是,如果使用 ffi 的好处是它可以在没有 c 编译器的系统上工作,那么如果我无论如何都要使用 c 编译器,那么使用它就没有意义了。感谢您的回答。
    • 啊,当我从 github 迁移到 bitbucket 时,完全忽略了更新此链接。谢谢你告诉我,@Tilo,我修复了链接。
    猜你喜欢
    • 2018-05-27
    • 1970-01-01
    • 1970-01-01
    • 2013-11-11
    • 2019-09-29
    • 1970-01-01
    • 1970-01-01
    • 2012-02-26
    • 1970-01-01
    相关资源
    最近更新 更多