DEV Community

loading...
Cover image for How to extend Ruby with C++

How to extend Ruby with C++

_adrian_e_ profile image Adrian E. ・2 min read

To extend Ruby with C++ is not that hard as you might think. Within a small project I created a barebone structure to getting started.

Here you will find answers for:

  • What libs do I need?
  • How can I compile?
  • And how can I interact with my C++-Class?

Let's start the adventure 🤠

The code

First we need something to work with. Well a featureless Car class work for that. The goal is to create and control the car. Well it's really featureless, because you can only give gas or stop it. But hey the car talks when it's born.

The libs

The default is mkmf (epsecially when you use the C-Api).

For C++ there is the great gem rice which is a great tool to bind a c++ class to ruby.

car_wrapper.cpp

// includes goes here
extern "C"
void Init_car_wrapper()
{
    Data_Type<Car> rb_cCar =
        define_class<Car>("Car")
            .define_constructor(Constructor<Car>())
            .define_method("gas", &Car::gas)
            .define_method("stop", &Car::stop);
}

So you wrap the class and every method into rice methods. To dig deeper you can read the documentation 🙂

compiling

This is really beautiful. Just create a extconf.rb file with the following content:

require "mkmf-rice"
create_makefile "car_wrapper"

Run ruby extconf.rb and you get a Makefile.

Finally run make and you get your Ruby-Extension as car_wrapper.so.

playground

And here you can play with it:

[1] pry(main)> require "./car_wrapper"
=> true
[2] pry(main)> mycar = Car.new
A new Car is born
=> #<Car:0x00005557f9db5bb8>
[3] pry(main)> mycar.gas(50)
=> 50
[4] pry(main)> mycar.stop()
=> 20
[5] pry(main)> mycar.stop()
=> -10
[6] pry(main)> mycar.stop()
=> -40
[7] pry(main)> exit
Good bye my car...

🥳 have fun 🎉

Photo credits

car: Thanks to MovienerdDeluxe - source
ruby-logo: Thanks to Yukihiro Matsumoto, Ruby Visual Identity Team - source

Discussion (0)

pic
Editor guide