Skip to content
This repository

How it works

With ffi-inliner you can inline snippets of C into your ruby script. The library takes care of compiling on the fly the C code interfacing to it through a generated FFI glue code. Using FFI you get interoperability among all ruby implementations that support FFI (e.g. JRuby, Rubinius, MRI Ruby).

Basic usage

You can activate the inliner extending your modules/classes with the Inliner module


require 'ffi-inliner'

module MyCLib
  extend Inliner
  inline 'int func_1() { return 1; }'
  inline 'int func_2() { return 2; }'
end

p MyCLib.func_1

class Foo
  include MyCLib
end

p Foo.new.func_1, Foo.new.func_2


Moreover, the inliner can be configured using the block form:


inline do |builder|
  builder.c 'int func_1() { return 0; }'
  builder.use_compiler Inliner::Compilers::TCC
end

or using the hash form:


inline 'int func_1() { return 0; }', :use_compiler => Inliner::Compilers::TCC

How to Include header files

You can include header files using Builder#include method:

inline do |builder|
  builder.include 'stddef.h' #=> produce #include <stddef.h>
  ...
end

By default Builder#include use the “bracket” form. If you want to add headers using the quoted form, pass :quoted => true as optional argument:

inline do |builder|
  builder.include 'myheader.h', :quoted => true #=> produce #include "myheader.h"
  ...
end

How to link against custom libraries

You can link your inline C against custom libraries using Builder#library:


inline do |builder|
  builder.library 'pthreads', 'libm'
  ...
end

Wrap C++ code (experimental)

Using the inliner you can even link to C++ code. The trick is to use extern “C” linkage to wrap C++ inside C. When using GPlusPlus (g++) compiler, the inliner encapsulates your C code in a extern “C” block.


require 'ffi-inliner'
 module Foo
   extend Inliner
   inline do |builder|
     builder.use_compiler Inliner::Compilers::GPlusPlus
     builder.c_raw <<-code
       #include <iostream>
       #include <string>
       using namespace std;
       class Greeter  {
         public:
           Greeter();
           string say_hello();
       };
       Greeter::Greeter() { };
       string Greeter::say_hello() {
         return "Hello foos!";
       };
       code
       builder.map 'char *' => 'string'
       builder.c <<-code
         const char* say_hello()
         { 
           Greeter greeter;
           return greeter.say_hello().c_str();
         }
       code
  end
end

p Foo.say_hello #=> "Hello foos!"

Something went wrong with that request. Please try again.