DEV Community

Cover image for Basic about Ruby C API
Marcelo Junior
Marcelo Junior

Posted on • Edited on

Basic about Ruby C API

Creating a Gem using Ruby C API

Sometimes we want to use a lib built with C language without any Ruby version, to make this we'll find a gem that integrates the lib C with Ruby. But, how this Gem was built?

In this article I'll show how to make this, using as an example the project musicrb, this Gem uses the lib of C vlc to play music on Ruby.

How is possible to integrate Ruby and C?

It's simple: Ruby is built using C, so we'll build a shared lib to the interpreter of Ruby use.

But do not trust in me, see the repository of language!

Basic about Ruby C API

Before starting to code our lib, we'll see some features in Ruby C API that we will use (p.s.: this tutorial is very basic if you want deep in this theme, my recommendation is the book Ruby Under a Microscope).

VALUE

See VALUE as a pointer to a Ruby's Object, since the Ruby is dynamic this feature is required. Then String, Number, Class, Module ... are accessed and modified by VALUE through functions of Ruby C API.

This is an example using VALUE as a pointer to String:

VALUE x;
x = rb_str_new_cstr("Hello, world!");

VALUE str;
str = rb_sprintf("pi = %f. %"PRIsVALUE" inspected: %+"PRIsVALUE, M_PI, x, x);

/* pi = 3.141593. Hello, world! inspected: "Hello, world!" */
Enter fullscreen mode Exit fullscreen mode

We can see that isn't required to pass the type of VALUE to methods like a programRuby!

DEFINE

The Gem musicrb has a class named Music, and has two static methods: play and stop.

Define this class and methods using Ruby is very simple:

class Music
  def play
    # Implementation ...
  end

  def stop
    # Implementation ...
  end
end
Enter fullscreen mode Exit fullscreen mode

The code in C will be like this:

// Headers ...

// Global variables ...
VALUE rb_cMusic;

VALUE
rb_music_stop(VALUE msc)
{
  // Implementation ...
}

VALUE
rb_music_play(VALUE msc, VALUE rpath)
{
  // Implementation ...
}

void
Init_musicrb(void)
{
  rb_cMusic = rb_define_class("Music", rb_cObject);
  rb_define_singleton_method(rb_cMusic, "play", rb_music_play, 1);
  rb_define_singleton_method(rb_cMusic, "stop", rb_music_stop, 0);
}

Enter fullscreen mode Exit fullscreen mode

rb_define_class: Define a class named "Music" that has a heritage with "Object".
rb_define_singleton_method: Define a singleton method to class "Music", in other words, a method of class. The last parameter of the function is the number of args.

Again, don't trust me!
See here the code.

Next steps

Okay, we already see the basics about the Ruby C API, but how to compile and test this code?

This post is already too long... I will follow up on the subject in the next article!

Goodbye, see you soon!

Top comments (0)