Marcelo Junior
Posted on June 21, 2023
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
Ruby
to "make our MakeFile" namedextconf.rb
on 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 😀
Posted on June 21, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.