Skip to content
PLAY VIDEO PLAY VIDEO PLAY VIDEO
By Yuji Yokoo

Extending Ruby with Extensions, FFI or Inline

Introduction

Ruby is a great programming language, but like all programming languages it is not suitable for everything. Sometimes it can make sense to use native libraries on the platform or C to improve the performance of slow Ruby code.

This post will explore calling C libraries and functions from Ruby. Although the methods mentioned in this post are not limited to just that, it is a very common use case.

Ruby has a few ways of integrating with native code. This post will look at native extensions, foreign function interface, and inline.

Native Extensions

Native extensions provide a method of interfacing with C code written in a certain way to make it accessible from Ruby. Typically, extensions are written in C, then built, loaded and called from Ruby. This is commonly used to interact with platform libraries by providing a wrapper or an additional API layer for them. RMagick and nokogiri are among the most popular gems that use extensions.

The notable disadvantages of this approach are that it is tightly coupled with the Ruby VM implementation, the extension must be built when installing or updating, and also it is in C.

Typically, a Ruby script is used to produce a Makefile, and the Makefile is then used to build the extension.

Extensions example

In a trivial example, there are a couple of files:

$ ls
extconf.rb helloext.c

extconf.rb contains this:

require 'mkmf'

dir_config('helloext')
create_makefile('helloext')

Also, helloext.c contains this:

#include "ruby.h"

VALUE hello_ext(VALUE self) {
  printf("Hello, extensions!\n");
  return Qnil;
}

void Init_helloext() {
  rb_define_global_function("hello_extensions", hello_ext, 0);
}

Building and execution goes like this:

$ ruby extconf.rb
creating Makefile
$ make
compiling helloext.c
linking shared-object helloext.bundle
$ ls
Makefile        extconf.rb      helloext.bundle helloext.c      helloext.o

This extension can be loaded and utilised from Ruby code:

$ irb
2.1.2 :001 > require './helloext.bundle'
=> true
2.1.2 :002 > hello_extensions
Hello, extensions!
=> nil

Foreign Function Interface

The Foreign Function Interface (FFI) is another method of interfacing with native binaries. It utilises libffi installed on the platform, and does not require compilation. It is very simple to use this for loading a platform library and calling its functions.

There are two common ways of using the FFI in Ruby; the ffi gem and Fiddle. Fiddle is part of the standard library and ffi is a gem. While the ffi gem has a wiki with lots of information, the Fiddle documentation is not extensive.

The main advantage of this approach is that it is cross-platform and not limited to MRI, since it is not tightly coupled with the Ruby implementation. Another advantage is that there is no need to build binaries once FFI is set up and functioning.

FFI example

The GitHub page for ffi contains this example:

require 'ffi'

module MyLib
  extend FFI::Library
  ffi_lib 'c'
  attach_function :puts, [ :string ], :int
end

MyLib.puts 'Hello, World using libc!'

An example with Fiddle which does the same might look like this:

require 'fiddle'

libc = Fiddle.dlopen('/usr/lib/libc.dylib')
libc_puts = Fiddle::Function.new(libc['puts'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
libc_puts.call("Hello, Fiddle!")

As they do not require compilation, they can be run directly like this:

$ ruby ffi-example.rb
Hello, World using libc!
$ ruby fiddle-example.rb
Hello, Fiddle!

Inline

RubyInline is a gem that makes it possible to embed "inline" C code in Ruby. Typically C code is embedded in string literals and built at runtime.

The notable advantage is that it is trivially simple to embed a little C code with RubyInline. The main disadvantages are that it requires compilation at runtime, and that code embedded in strings can be hard to work with.

RubyInline example

require "inline"

class HelloInline
  inline do |hello|
    hello.c '
      void hello_inline() {
        printf("Hello, RubyInline!\n");
      }
    '
  end
end

HelloInline.new.hello_inline

RubyInline takes care of building the binary, so this can be called directly too.

$ ruby inline.rb
Hello, RubyInline!

Final Thoughts

Although I love how easy it is to embed a small C function with RubyInline, I would not like to embed C code in strings, or to compile it at runtime. Previously I have only used extensions, but after writing this post, I would probably use ffi over extensions.

Latest Articles by Our Team

Our expert team of designers and developers love what the do and enjoy sharing their knowledge with the world.

We Hire Only the Best

reinteractive is Australia’s largest dedicated Ruby on Rails development company. We don’t cut corners and we know what we are doing.

We are an organisation made up of amazing individuals and we take pride in our team. We are 100% remote work enabling us to choose the best talent no matter which part of the country they live in. reinteractive is dedicated to making it a great place for any developer to work.

Free Community Workshops

We created the Ruby on Rails InstallFest and Ruby on Rails Development Hub to help introduce new people to software development and to help existing developers hone their skills. These workshops provide invaluable mentorship to train developers, addressing key skills shortages in the industry. Software development is a great career choice for all ages and these events help you get started and skilled up.

  • Webinars

    Webinars

    Webinars are our online portal for tips, tricks and lessons learned in everything we do. Make the most of this free resource to help you become a better developer.

    Learn more about webinars

  • Installfest

    Installfest

    The Ruby on Rails Installfest includes a full setup of your development environment and step-by-step instructions on how to build your first app hosted on Heroku. Over 1,800 attendees to date and counting.

    Learn more about Installfest

  • Development Hub

    Development Hub

    The Ruby on Rails Development Hub is a monthly event where you will get the chance to spend time with our team and others in the community to improve and hone your Ruby on Rails skills.

    Learn more about Development Hub

Get the “reinteractive Review” Monthly Email