How to compile C code for use in the program Ruby?
Write a Makefile to compile this program as shared lib to a program Ruby to use can be hard work, to solve this problem Ruby's core created the module MakeMakefile.
- First: write a script in
Rubyto "make our MakeFile" namedextconf.rbon the same folder of programC:
require 'mkmf'
create_makefile 'foo'
This simple code generates a MakeFile to the file foo.c.
- Second: Run
ruby extconf.rb
We'll find our Makefile in the current path! 🎉
But... and the file foo.c?
Writing our C Extension
See below basic skeleton of our C Extension:
#include "ruby.h"
void Init_foo()
{
// Your C code goes here
}
First include the lib ruby.h to use functions, constants... of Ruby.
Second create a function that returns void, named Init_ plus the name used in extconf.rb. In this example Init_foo.
Bingo! Our first C Extension is done!
To see the shared lib compiled by this code:
$ ruby extconf.rb
$ make
$ ls
Makefile extconf.rb foo.c foo.o foo.so
Let's create a Class and a Method to say "hello"?
Adding Class and Method to foo.c
See below how file.c turned out:
#include "ruby.h"
VALUE rb_hello(VALUE class) {
VALUE str = rb_str_new_cstr("hello!");
rb_funcall(rb_mKernel, rb_intern("puts"), 1, str);
return Qnil;
}
void Init_foo()
{
VALUE class = rb_define_class("Greeting", rb_cObject);
rb_define_singleton_method(class, "hello", rb_hello, 0);
}
Like the first part of this article, we'll define the class Greeting using the function rb_define_class inheriting from Object. And we'll define the method of class hello using rb_define_singleton_method passing the function rb_hello as a parameter.
The function rb_hello should return VALUE and receive as a parameter the class. This function transforms a string of C to a string of Ruby using the method rb_str_new_cstr, then call method puts of Kernel through of function rb_funcall(rb_mKernel, rb_intern("puts"), 1, str). And finally returns Qnil, the same nil of Ruby.
In Ruby this code is like this:
class Greeting
def self.hello
Kernel.puts "hello" # or puts "hello"
end
end
LET'S RUN IT!
To test our work until here compile the C Extension again:
$ ruby extconf.rb
$ make
Then open the irb inside of folder of shared lib and run this code:
require './foo'
Greeting.hello
# hello!
🎉 🎉 YEAH! ITS DONE! 🎉 🎉
Next steps
Finally, we compile our C Extension! However, we don't create a Gem yet 🙄...
In the next article, we'll make this!
See you later 😀
Top comments (2)
With this tutorial I could make my first gem.
Tankyou
I'm happy that this tutorial help you ❤️