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.