C extensions are comprised of two general pieces:
To get started with your first extension put the following in a file named extconf.rb
:
require 'mkmf'
create_makefile('hello_c')
A couple of things to point out:
First, the name hello_c
is what the output of your compiled extension is going to be named. It will be what you use in conjunction with require
.
Second, the extconf.rb
file can actually be named anything, it's just traditionally what is used to build gems that have native code, the file that is actually going to compile the extension is the Makefile generated when running ruby extconf.rb
. The default Makefile that is generated compiles all .c
files in the current directory.
Put the following in a file named hello.c
and run ruby extconf.rb && make
#include <stdio.h>
#include "ruby.h"
VALUE world(VALUE self) {
printf("Hello World!\n");
return Qnil;
}
// The initialization method for this module
void Init_hello_c() {
VALUE HelloC = rb_define_module("HelloC");
rb_define_singleton_method(HelloC, "world", world, 0);
}
A breakdown of the code:
The name Init_hello_c
must match the name defined in your extconf.rb
file, otherwise when dynamically loading the extension, Ruby won't be able to find the symbol to bootstrap your extension.
The call to rb_define_module
is creating a Ruby module named HelloC
which we're going to namespace our C functions under.
Finally, the call to rb_define_singleton_method
makes a module level method tied directly to the HelloC
module which we can invoke from ruby with HelloC.world
.
After having compiled the extension with the call to make
we can run the code in our C extension.
Fire up a console!
irb(main):001:0> require './hello_c'
=> true
irb(main):002:0> HelloC.world
Hello World!
=> nil