An Introduction to Mini Ruby

Ruby is used in a wide variety of projects today, but has gained popularity in web development with Ruby on Rails. With mruby, the latest language implementation, Ruby can be embedded into other applications.

Installation

The mruby project is hosted on Github. There are currently no binary distributions available, but it is easy enough to build mruby from source. mruby uses the bison parser generator, which we need to install before we can build from source.

apt-get install bison build-essential
Install bison and compiler tools (Debian/Ubuntu)

Make sure you have Git installed on your system and then execute the following commands:

git clone git://github.com/mruby/mruby.git
cd mruby
make
Download and build mruby from source

This will clone the repository from Github and compile mruby. After compilation has finished, you should have the mruby binaries in bin/, library files in lib/ and header files in include/.

Executables

The compilation process generates three binaries in the bin/ directory. Lets inspect them one by one.

mruby

This is the equivalent to the normal Ruby binary your have with MRI Ruby. You can execute mruby scripts or just check them for syntax errors.

mirb

mirb is the mruby variant of the interactive ruby shell, you probably already know from standard Ruby. It provides an easy and interactive interface where you can write ruby code and execute it on-the-fly.

$ ./mirb 
mirb - Embeddable Interactive Ruby Shell

This is a very early version, please test and report errors.
Thanks :)

> s = "awesome"
 => "awesome"
> p "Ruby is #{s}"
"Ruby is awesome"
 => "Ruby is awesome"
Embeddable Interactive Ruby Shell

mrbc

The mrbc binary is the mruby bytecode compiler. It translates mruby scripts into either rite bytecode for the RiteVM (which is the name of the VM mruby uses) or transforms it into a C program. While mruby can directly execute Ruby scripts you can use mrbc to precompile the scripts into bytecode. This obviously makes execution of your programs faster, as the script does not have to be parsed every time you want to execute it.

Say you have a script called test.rb and want to compile it to bytecode and then execute it with mruby. All you need to do is the following:

./bin/mrbc test.rb
./bin/mruby -b test.mrb
Compiling and executing a mruby script

Embedding mruby

mruby is designed to be embedded into other applications. It provides an easy to use C API which can be used to execute scripts or simply hard-coded strings or to extend mruby by providing custom classes that interface with your application. A "Hello World" like example for the C API is the following:

#include <stdlib.h>
#include <stdio.h>

#include <mruby.h>
#include <mruby/compile.h>

int main(void)
{
  mrb_state *mrb = mrb_open();
  char code[] = "5.times { puts 'Ruby is awesome!' }";

  mrb_load_string(mrb, code);
  return 0;
}
C program with mruby bindings (main.c)

This small snippet creates a new instance of mruby using mrb_open (defined in mruby.h) and then loads and executes the character array with ruby code using mrb_load_string. In order to compile this code we need to tell gcc, to link the libmruby library. We also need to include the math library (-lm) which is not linked with libmruby.

$ gcc -Iinclude main.c lib/libmruby.a -lm -o main.out
$ ./main.out
Ruby is awesome!
Ruby is awesome!
Ruby is awesome!
Ruby is awesome!
Ruby is awesome!
Compile and run C binary with libruby

There are several ways by which you can optimize mruby itself. For one you can force the mruby runtime to use float instead of double values for representing floating point number by simply defining the MRBUSEFLOAT constant as compiler option (-DMRBUSEFLOAT). Other options can be found in include/mrbconf.h:

/* -DDISABLE_XXXX to drop the feature */
#define DISABLE_REGEXP          /* regular expression classes */
//#define DISABLE_SPRINTF       /* Kernel.sprintf method */
//#define DISABLE_MATH          /* Math functions */
//#define DISABLE_TIME          /* Time class */
//#define DISABLE_STRUCT        /* Struct class */
//#define DISABLE_STDIO         /* use of stdio */
include/mrbconf.h

By default only regular expressions are disabled.

Limitations

mruby comes with a number of limitations to make it as light as possible. The probably most notable feature that has been left out, is the ability to require files. Requiring other files is an expensive operation and does not fit well into the design of mruby. Similarly forks and threads are not available for mruby scripts.

Conclusions

mruby is still in development, but there already are a number of good projects utilizing it. MobiRuby brings mruby to the iOS platform and allows you to build apps for mobile devices. mruby has a low-memory footprint and is in many ways similar to Lua. Lua is extensively used in scripting video games or as a way to influence httpd request processing in popular webservers like Apache, lighttpd or NginX. For Apache, there already is a mod_mruby that is developed as an alternative to Lua.

Additional Ressources

Comments


Avatar
Fabian Müller – over 1 year ago

Hi Mate, nice article!

Avatar
Xuejie Xiao – over 1 year ago

Hi Fabian,

I read about this article a few days ago. It is really interesting! First I want to thank you for writing such a nice article!

I played with mruby for quite some time and I managed to port it onto a browser via emscripten. The source code is at here. And I use your main.c program in this article as an entrypoint now(it's in src/main.c). I want to ask if you are okay with this. And what license do you want to grant this file? And it is certainly okay if you have other plans about the source code, I can remove it ASAP:)

Thanks for your help!

Avatar
Fabian Becker – over 1 year ago

Thank you for the comment!

You can of course use the code under the MIT License that you already use for mruby-browser. Thanks for mentioning the article in your README!

Avatar
– 6 months ago

Great tutorial! Very helpful. I'm wondering how to take the next step...write Ruby in a separate file and "require" it in the C file to be executed by mruby. I'm still pretty new to C so this part is a little over my head right now.

First sign in through Github or Twitter