First experiments embedding mruby

The philosophy of mruby is to be a lightweight implementation of the Ruby ISO standard with some limitations. Different from the usual Ruby runtime, specially MRI, mruby, using RiteVM, is designed to be a modular and embedded version of ruby. It’s pretty small and fast, actually, and easily extended with C. A good OO auternative to Lua for embbedded, although lua is way faster today.

code integrations, is easy as hell

clone mruby repo

$ cd ~/Workspace/embbeded
$ git clone https://github.com/mruby/mruby.git

Then install it as explained here

Now, let’s test with a simple inline code (01.c):

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

int
main(void)
{
  mrb_state *mrb = mrb_open();
  if (!mrb) { /* handle error */ }
  // mrb_load_nstring() for strings without null terminator or with known length
  mrb_load_string(mrb, "puts 'hello world'");
  mrb_close(mrb);
  return 0;
}

compile it with:

$ gcc -std=c99 -Imruby/include 01.c -o aaa mruby/build/host/lib/libmruby.a -lm

as expected, the string “Hello world” will be printed. Now, to embbed a small ruby file, I tested this small C code(02.c):

#include <stdio.h>
#include <mruby.h>
#include <mruby/dump.h>

static mrb_value mrb_greet(mrb_state *mrb, mrb_value self) {
  printf("Hey ho mofo!\n");
  return mrb_nil_value();
}

mrb_value mrb_boo(mrb_state* mrb, mrb_value self){
	mrb_int i = 0; // retrieve one arg of type int (see mruby.h)
	mrb_get_args(mrb, "i", &i);
	printf("iiiiiha %d hae hae\n", (int)i);
	return mrb_nil_value();
}

int main(void){
  mrb_state *mrb = mrb_open();
  if (!mrb) { /* handle error */ }
  mrb_define_method(mrb, mrb->object_class, "greet!", mrb_greet, MRB_ARGS_NONE());
  mrb_define_method(mrb, mrb->object_class, "boo!", mrb_boo, MRB_ARGS_REQ(1));
  FILE *fp = fopen("testa.mrb", "r");
  mrb_load_irep_file(mrb, fp);
  mrb_close(mrb);
  return 0;
}

There are two importante things here. First, I had to add <mruby/dump.h> for mrb_load_irep_file and remove <mruby/compile.h> to decrease generated binary file. Second, we have to export any method that we define in C with mrb_define_method.

Now for the testa.rb we have


puts 'helloooo worldi'
greet!
puts 'here we go'
boo! 12
puts 'end'

After that, generate it’s bytecode with:

$ cd ~/Workspace/embbeded
$ mruby/bin/mrbc testa.rb

which will generate `testa.mrb`.

$ cd ~/Workspace/embbeded
$ gcc -std=c99 -Imruby/include 02.c -o aaa mruby/build/host/lib/libmruby.a -lm
$ ./aaa
helloooo worldi
Hey ho mofo!
here we go
iiiiiha 12 hae hae
end

To show that this works.

Also, as we are junt reading from a file, we could store it within an array. That would work as well.
just include <mruby/irep.h> then create an anyarray[] = { 0x45, 0x54..., 0x08 }; and, finally, call with mrb_load_irep(mrb, anyarray);

mruby is easy to integrate with anything and is getting faster everyday. So play with it a little. Enjoy.