David Miani
David Miani

Reputation: 14668

How to use ruby ffi for calling custom c code in a ruby gem

I want to create a ruby gem that calls a c function I have written. For example:

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

This would be in a c file in my rubygem. I would then want to be able to call it in ruby, by wrapping it with the ffi interface:

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

However I'm not sure how to set this up, so that when the gem is installed the c file would compile into a library (with the name 'MyLib'), and the ffi will detect the library and use it in the code above.

Does anyone know how to do this, or is there a better way of going about this? Note that I would rather not use the standard way of extending ruby (as described in the The Pragmatic Programmer's Guide Extending Ruby section) since that only will work with the standard ruby interpretor (I believe).

I have been using jeweler for building my gems, if that matters for this question.

Upvotes: 2

Views: 1724

Answers (1)

buruzaemon
buruzaemon

Reputation: 3907

nanothief, first you would have to consult your C compiler to compile your C code into a library.

For example, assuming the function above is in a file named MyLib.c, and assuming you use GCC:

$ gcc -c MyLib.c

... which results in MyLib.o object file

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

... which results in MyLib.so shared object, which is your library file (but keep in mind that while this library may compile fine for me in my environment, it may not work for you in your environment).

Then, in your Ruby code, you would need to load the FFI gem with:

require 'ffi'

However, the beauty of using the FFI/Ruby approach is that you do not need to make assumptions about the your gem users' environment. Hence, in most cases, the library which you load with ffi_lib is expected to be already compiled and existing somewhere on the library path of your gem user's machine.

With a C extension, you would have to package up the C source with your gem and have your gem users compile the C source themselves. This might not work if your users do not have access to a C compiler for their environment, or if they are using JRuby (only has limited support for C extentions, IIRC).

If you are interested, you could have a look at this gem I wrote that leverages FFI.

Upvotes: 5

Related Questions