Ruby programs can now easily call native C library functions via the FFI
mechanism.
Basics: require 'ffi' and attach_function
The require 'ffi'
directive will load and initialize the FFI
library. You then need to use extend FFI::Library
in a module you wish to attach native functions to, and finally, use attach_function
to link the native C functions into the module.
Hello, World using FFI
require 'ffi'
module Hello
extend FFI::Library
ffi_lib FFI::Library::LIBC
attach_function :puts, [ :string ], :int
end
Hello.puts("Hello, World")
The interesting part above is the attach_function
call. It requests that a C function named puts
which takes a :string argument and returns an :int, be attached to the Hello module.
The attach_function
method locates the C function in a specific external library (i.e. libc in the example). To use it, you need to supply the name of the function to load, the parameter types the function takes, and the return type of the function.
Long running C functions should be declared as blocking functions by adding blocking: true
to attach_function
as in the following example. See the Callback chapter for a discussion of the impact of blocking: true
.
Hello, Windows using FFI
require 'ffi'
module HelloWin
extend FFI::Library
ffi_lib 'user32'
ffi_convention :stdcall
attach_function :, :MessageBoxA,[ :pointer, :string, :string, :uint ], :int, blocking: true
end
rc = HelloWin. nil, 'Hello Windows!', 'FFI on Windows', 1
puts "Return code: #{rc}"
Using the Windows API is almost as easy as the previous example. Typically you need to tell FFI what Windows library to search via the ffi_lib
method and tell FFI to use the stdcall convention used by the Windows API. The ffi_convention
method tells FFI what calling convention to use.
You also need to ensure that you attach the correctly named function to your Ruby module. For all functions that take string arguments, the Windows API provides "short name" macros that expand to function names with a suffix indicating ASCII or Unicode. ANSI versions are suffixed with a "A", and Unicode versions are suffixed with a "W".
Parameter and return types
Here below there is a partial list of the types supported by FFI. For a more exhaustive list you may look at [[Types]] page.
:char
and:uchar
- 8 bit signed and unsigned values:short
and:ushort
- 16 bit signed and unsigned values:int
and:uint
- 32 bit signed and unsigned values:long_long
and:ulong_long
- 64 bit signed and unsigned values:long
and:ulong
- native cpu word (32 bit or 64bit) signed and unsigned values. Equivalent to C 'long' type.:float
and:double
:string
- C string, NULL terminated.:pointer
- a C pointer- struct by value -> see chapter Structs
- struct by pointer -> see chapter Structs