初めてのmruby (Mac OS X上でのみ確認)
Railsですっかりメジャーな言語になったRubyで組込みプログラムが書けちゃうニューカマー[mruby][https://github.com/mruby/mruby]にちょっと興味津々な今日このごろです。
数年前に関わったプロジェクトがVB+78Kマイコンで制御される工作機械だったこともあって、電気的な知識は相変わらずゼロに近いまんまですがフィジカルコンピューティングには強く惹かれています。ソフトしか使ってない人間からすると、モーターが動いたり発光ダイオード(LED)が明滅することにロマンと言うか、一種あこがれを感じるのです。
そんな訳で本屋で見かけたちょんまげプリントが可愛いJapaninoなんかに発作的に手を出してLEDチカチカだけで挫折したり、マルツパーツ館で見つけたLPC1769買ってやっぱりLチカで終わったした私としては、無闇に基盤を買っても悲しい思いをするだけという確信がありまして、物欲よりもまずは知識を深めるためにMac上で動かしてみることにした訳です。
mrubyとは
前々から名前は知っていたものの、今日調べ初めたばっかりで良く分かってないのですが、組込み向けに軽量化されたRubyです。詳しくはこちらの文章をお読み下さい。MobiRubyを開発されている増井さんという方が書かれたブログ記事も分かりやすいかと思います。
mrubyは一般にリリースされてから(まだ正式じゃないものかも)それなりに日数は経過しているようですが、ちょっと検索した限りでは情報も少なめで何から初めたら良いのやら状態なんですが、ハード込みなら既に入門用キットもあって、これを買えば取り敢えずLCDパネルと組合せてばりばり使えるみたいです。どうせなら同じ値段で講習受けたほうがお得な気はしますけど。
とりあえずパソコン上で動かしてみる
仕事で必要に迫られたりしないかぎりは講習を受ける事はまずなさそうですが、そもそもmrubyは組込みボードのためだけの言語ではなく、先ほども出てきたMobiRubyやmod_mrubyなんてのもあったりしますので、パソコン上でも普通に動作します。
ですのでさっそくインストールから始めてみましょう。
git clone https://github.com/mruby/mruby
cd mruby
ruby ./minirake
ちょー簡単ですね。コンパイルが問題なく終わればbinディレクトリの下にmirb
、mrbc
、mruby
が出来上がっているはずです。
次に実行するrubyプログラムを用意します。定番のハローワールドちゃんです。
p 'Hello Mruby !'
まずはきちんと動作するか確認です。
$ ./bin/mruby hello.rb
"Hello Mruby !"
mrubyで実行する分にはCRubyとなんら変わりがないので次にコンパイルしてみましょう。エラーが出なければ同じディレクトリ内にhello.mrb
という中間コードのファイルが出来ているはず。
$ ./bin/mrbc hello.rb
最初と違って今度はオプションを追加して実行します。当然ながらこちらも実行結果は同じです。
$ ./bin/mruby -b hello.mrb
"Hello Mruby !"
ここまではコマンドを使っての実行なので、コンパイル作業はあったものの、やはりそれほどCRubyでの実行と変わるところがありませんので、もう少し踏み込んで組込みっぽく動かしたいところなので、いよいよC言語の出番ですね。mruby.c
を参考にざっとソースを書いてみました。
#include <mruby.h>
#include <mruby/dump.h>
#include <mruby/irep.h>
#include <mruby/proc.h>
#include <stdlib.h>
extern const uint8_t hello[];
int
main(int argc, char **argv)
{
int n;
FILE *file;
mrb_state *mrb = mrb_open();
mrb = mrb_open();
file = fopen("./hello.mrb", "rb");
n = mrb_read_irep_file(mrb, file);
if (n < 0) {
fprintf(stderr, "failed to load mrb file: hello.mrb\n");
return EXIT_FAILURE;
}
mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb));
if (mrb->exc) {
fprintf(stderr, "exception occur !\n");
return EXIT_FAILURE;
}
mrb_close(mrb);
fclose(file);
return n == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
でソースをさっそくコンパイルして実行してみます。
gcc -Wall -I./include -L./build/host/lib -o hello_mrb mrb_main.c -lmruby
./hello_mrb
"Hello Mruby !"
これでhello_mrb
コマンドとhello.mrb
ファイルのセットで実行出来るようになりましたが、ファイル開いて読みこむ作業が必要というのも何か面倒というか、単一のバイナリで実行したい場合もあると思います。コンパイルする時にmrbc
のヘルプを見たらちょっと気になる部分が、、
$ ./bin/mrbc -h
Usage: ./bin/mrbc [switches] programfile
switches:
-c check syntax only
-o<outfile> place the output into <outfile>
-v print version number, then turn on verbose mode
-g produce debugging information
-B<symbol> binary <symbol> output in C language format
--verbose run at verbose mode
--version print the version
--copyright print the copyright
$
-B
オプションがちょっとあれな感じですよね(笑)。でっさっそく実行$ ./bin/mrbc -Bhello hello.rb
して出来上がったhello.c
がこんな感じになります。
#include <stdint.h>
const uint8_t hello[] = {
0x52,0x49,0x54,0x45,0x30,0x30,0x30,0x31,0x5f,0x81,0x00,0x00,0x00,0x66,0x4d,0x41,
0x54,0x5a,0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0x48,0x30,0x30,
0x30,0x30,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x01,0x00,0x03,0x00,0x00,
0x00,0x04,0x00,0x80,0x00,0x06,0x01,0x00,0x00,0x3d,0x00,0x80,0x00,0xa0,0x00,0x00,
0x00,0x4a,0x00,0x00,0x00,0x01,0x10,0x00,0x0d,0x48,0x65,0x6c,0x6c,0x6f,0x20,0x4d,
0x72,0x75,0x62,0x79,0x20,0x21,0x00,0x00,0x00,0x01,0x00,0x01,0x70,0x00,0x45,0x4e,
0x44,0x00,0x00,0x00,0x00,0x08,
};
実はこれをどうやって使うのか分かるまでちょっと時間がかかったのですが、とりあえず動くようにしたのが以下のコードです。さっきよりずっと短くなって組込みっぽさがアップしているのが分かると思います(笑)。
#include <mruby.h>
#include <mruby/irep.h>
extern const uint8_t hello[];
int
main(int argc, char **argv)
{
mrb_state *mrb = mrb_open();
mrb_load_irep(mrb, hello);
if (mrb->exc) {
printf("Exception Occur !");
return 9;
}
mrb_close(mrb);
return 0;
}
先ほど同様のコマンドでコンパイルして実行!
gcc -Wall -I./include -L./build/host/lib -o hello main.c hello.c -lmruby
./hello
"Hello Mruby !"
これで一つのバイナリーになってスッキリです。
実際に組込みボード上で実行するためにはまだまだいくつもハードルが有ると思いますが、まあ触りを楽しむならこの程度でご満足頂けたのではないかと思います。mruby今後も要注目です。