mruby をさわってみた
mruby とは
組込み向けに軽量化されたRuby。mruby 単体で実行するというよりは、組み込み機器や Cなどで書いたアプリのなかに、まるごとmrubyアプリケーション+実行環境
を組み込んで利用する感じ。
mruby を MacOSX 上でコンパイル
mruby をさわるため、まずソースからコンパイルする。コンパイルは拍子抜けするほど簡単。以下が必要だが、Command Line Tools をいれてれば足りる。
環境
- gcc
- ruby
- bision
手順
-
ソースのダウンロード(2fe556d)
git clone https://github.com/mruby/mruby cd mruby
-
コンパイル(速い)
$ time ruby minirake (in /Users/PMAC051S/src/github.com/mruby/mruby) CC src/array.c -> build/host/src/array.o CC src/backtrace.c -> build/host/src/backtrace.o : real 0m14.238s user 0m8.442s sys 0m3.884s
コンパイルされたもの
こんなファイルが出来る。
$ ls -l bin/* build/host/lib/libmruby.a
-rwxr-xr-x 1 harasou staff 881116 5 2 18:27 bin/mirb*
-rwxr-xr-x 1 harasou staff 656568 5 2 18:27 bin/mrbc*
-rwxr-xr-x 1 harasou staff 920456 5 2 18:27 bin/mrdb*
-rwxr-xr-x 1 harasou staff 879992 5 2 18:27 bin/mruby*
-rwxr-xr-x 1 harasou staff 898124 5 2 18:27 bin/mruby-strip*
-rw-r--r-- 1 harasou staff 2027736 5 2 18:27 build/host/lib/libmruby.a
- mirb: mruby の irb
- mrbc: mruby スクリプトのコンパイラ。mrb 形式などを出力する。
- mrdb: mruby のデバッガ。
- mruby: mruby のインタプリンタ
- mruby-strip: ???
- libmruby.a: mruby のライブラリ
それぞれ使ってみた
mirb
irb の mruby 版
$ bin/mirb
mirb - Embeddable Interactive Ruby Shell
> puts "Hello, World !"
Hello World !
=> nil
>
mrbc
mruby スクリプトをデフォルトだと mrb 形式にコンパイルする。 mrb 形式というのは、mruby の独自フォーマットでプラットフォーム非依存。mrb 形式については、いずれ調査したい。
$ bin/mrbc --help
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
-e generate little endian iseq data
-E generate big endian iseq data
--verbose run at verbose mode
--version print the version
--copyright print the copyright
puts "Hello, world!"
$ bin/mrbc hello.rb
$ ls -l hello.*
-rw-r--r-- 1 harasou staff 103 5 2 23:37 hello.mrb
-rw-r--r-- 1 harasou staff 22 5 2 23:37 hello.rb
$ file hello.mrb
hello.mrb: data
$ od -tcx1 hello.mrb
0000000 R I T E 0 0 0 3 022 372 \0 \0 \0 g M A
52 49 54 45 30 30 30 33 12 fa 00 00 00 67 4d 41
0000020 T Z 0 0 0 0 I R E P \0 \0 \0 I 0 0
54 5a 30 30 30 30 49 52 45 50 00 00 00 49 30 30
0000040 0 0 \0 \0 \0 A \0 001 \0 004 \0 \0 \0 \0 \0 004
30 30 00 00 00 41 00 01 00 04 00 00 00 00 00 04
0000060 \0 200 \0 006 001 \0 \0 = \0 200 \0 240 \0 \0 \0 J
00 80 00 06 01 00 00 3d 00 80 00 a0 00 00 00 4a
0000100 \0 \0 \0 001 \0 \0 \r H e l l o , w o
00 00 00 01 00 00 0d 48 65 6c 6c 6f 2c 20 77 6f
0000120 r l d ! \0 \0 \0 001 \0 004 p u t s \0 E
72 6c 64 21 00 00 00 01 00 04 70 75 74 73 00 45
0000140 N D \0 \0 \0 \0 \b
4e 44 00 00 00 00 08
0000147
$ bin/mrbc -Bhello hello.rb
$ ll hello*
-rw-r--r-- 1 harasou staff 752 5 3 00:25 hello.c
-rw-r--r-- 1 harasou staff 103 5 2 23:37 hello.mrb
-rw-r--r-- 1 harasou staff 22 5 2 23:37 hello.rb
$ cat hello.c
/* dumped in little endian order.
use `mrbc -E` option for big endian CPU. */
#include <stdint.h>
const uint8_t
#if defined __GNUC__
__attribute__((aligned(4)))
#elif defined _MSC_VER
__declspec(align(4))
#endif
hello[] = {
0x45,0x54,0x49,0x52,0x30,0x30,0x30,0x33,0x64,0x92,0x00,0x00,0x00,0x67,0x4d,0x41,
0x54,0x5a,0x30,0x30,0x30,0x30,0x49,0x52,0x45,0x50,0x00,0x00,0x00,0x49,0x30,0x30,
0x30,0x30,0x00,0x00,0x00,0x41,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x04,
0x06,0x00,0x80,0x00,0x3d,0x00,0x00,0x01,0xa0,0x00,0x80,0x00,0x4a,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0x00,0x00,0x0d,0x48,0x65,0x6c,0x6c,0x6f,0x2c,0x20,0x77,0x6f,
0x72,0x6c,0x64,0x21,0x00,0x00,0x00,0x01,0x00,0x04,0x70,0x75,0x74,0x73,0x00,0x45,
0x4e,0x44,0x00,0x00,0x00,0x00,0x08,
};
C形式はどうやって使うのかも不明なので今度調べる。mrb_read_irep(mrb, hello)
で読み込む?
mruby
mruby のインタプリンタ。mrb形式のファイルを渡す場合は、-b
オプションで。
$ bin/mruby -b hello.mrb
Hello, world!
libmruby.a
Cから利用する際のライブラリ。
#include <mruby.h>
#include <mruby/compile.h>
int main(void) {
mrb_state* mrb;
mrb = mrb_open();
mrb_load_string(mrb,"puts 'Hello World!'");
mrb_close(mrb);
return 0;
}
$ gcc -o hello -Iinclude hello.c build/host/lib/libmruby.a
$ ./hello
Hello World!
ちなみにアーカイブに入っていたオブジェクトファイルは以下のような感じだった。
$ ar t build/host/lib/libmruby.a
__.SYMDEF SORTED
array.o
backtrace.o
class.o
codegen.o
compar.o
crc.o
debug.o
dump.o
enum.o
error.o
etc.o
fmt_fp.o
gc.o
hash.o
init.o
kernel.o
load.o
numeric.o
object.o
pool.o
print.o
proc.o
range.o
state.o
string.o
symbol.o
variable.o
version.o
vm.o
y.tab.o
mrblib.o
kernel.o
sprintf.o
gem_init.o
print.o
gem_init.o
math.o
gem_init.o
time.o
gem_init.o
struct.o
gem_init.o
gem_init.o
string.o
gem_init.o
numeric_ext.o
gem_init.o
array.o
gem_init.o
hash-ext.o
gem_init.o
range.o
gem_init.o
proc.o
gem_init.o
symbol.o
gem_init.o
mt19937ar.o
random.o
gem_init.o
object.o
gem_init.o
mruby_objectspace.o
gem_init.o
fiber.o
gem_init.o
gem_init.o
gem_init.o
gem_init.o
kernel.o
gem_init.o
gem_init.o
mrbd
デバッガ。gdb と似たような感じ。
$ bin/mrdb hello.rb
(hello.rb:1) help
Commands
b[reak] -- Set breakpoint
c[ontinue] -- Continue program being debugged
d[elete] -- Delete some breakpoints
dis[able] -- Disable some breakpoints
en[able] -- Enable some breakpoints
ev[al] -- Evaluate expression
h[elp] -- Print this help
i[nfo] b[reakpoints] -- Status of breakpoints
l[ist] -- List specified line
p[rint] -- Print value of expression
q[uit] -- Exit mrdb
r[un] -- Start debugged program
s[tep] -- Step program until it reaches a different source line