Transcript
Page 1: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mrubyについて第16回 岡山Ruby, Ruby on Rails 勉強会

Page 2: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

自己紹介

・小西 雅也

・Twitter: @ore_public・Github: https://github.com/ore-public・Ruby歴 12年くらい

・株式会社リゾーム 勤務

Page 3: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

自己紹介

・言語処理系の技術が趣味

・プログラミング言語が趣味

・OSのクリーンインストールが趣味

Page 4: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

自己紹介

・JRubyでテトリス

https://github.com/ore-public/tetris

Page 5: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

るびま10周年https://twitter.com/gunjisatoshi/status/489194078139990016

Page 6: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

アジェンダ

・mrubyとは

・ビルド

・mrbgemについて

・CRubyと比べる

・mrbgemを作ってみる

・mrbgemを元にmruby内部を少し解説

Page 7: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mruby・省メモリ版ruby・組み込み用途に使いやすい(らしい)・JRubyやRubiniusの様な「Ruby言語」の

 別実装ではない

・mrubyという別の仕様をもった言語

Page 8: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

ビルド$ git clone [email protected]:mruby/mruby.git$ cd mruby$ ruby ./minirake (もしくは rake )

以下の4つが出来上がる./bin/mruby    mruby本体

./bin/mirb CRubyで言う irb

./bin/mrbc コンパイラ(rubyコード → バイトコード)

./bin/mruby-strip  Todo

Page 9: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mrbgem・mrubyのビルド時にmrbgemのコードを取得

・mrubyにgemの内容も組み込まれる

・CRubyのgemのような依存関係の解決はない

・ビルドの設定ファイル (build_config.rb)で指定する

MRuby::Build.new do |conf| if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR'] toolchain :visualcpp else toolchain :gcc end enable_debug

conf.gem :git => 'https://github.com/ore-public/mruby-fizzbuzz' conf.gem ‘../fizzbuzz’ conf.gembox 'default'end

Page 10: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mrbgem#gitリポジトリ指定

conf.gem :git => 'https://github.com/ore-public/mruby-fizzbuzz'

#ファイルパス指定

conf.gem ‘../fizzbuzz’

#gembox指定

conf.gembox 'default'  #依存関係の解決などにつかう

Page 11: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mrbgems・gemboxmrbgemsディレクトリに .gemboxファイルがありその中身に記述されているmrbgemがビルドされる

Page 12: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mrbgems

MRuby::GemBox.new do |conf| # Use standard Kernel#sprintf method conf.gem :core => "mruby-sprintf"

# Use standard print/puts/p conf.gem :core => "mruby-print"

# Use standard Math module conf.gem :core => "mruby-math"

default.gembox(一部抜粋)

Page 13: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mrbgems・以下のものもmrbgemsになっている

mrubyコマンド

mirbコマンド

・gembox defaultを外してビルドすると

mrbcしかビルドされない

Page 14: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

CRubyと比べるCRuby (rbenvにてruby2.1.2) rubyコマンド 2,413,276バイト

mruby mrubyコマンド 705,956バイト

1/3くらい

※Mac OS X 10.9.4にてビルド時

Page 15: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

CRubyと比べるmrbgemsを一切いれずにビルド時の出力

・構成ファイル結構少ない

・これなら読めそうな気がしてくる

Page 16: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

CRubyと比べる・array.cを比べる (Arrayクラスの実装)

CRuby (ruby2.1.2)  約5700行 mruby  約1100行

・読めそうな気がしてくる

Page 17: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

CRubyと比べる・Arrayに定義されているメソッド数を比べる

CRuby > Array.instance_methods(false).size => 90

mruby > Array.instance_methods(false).size => 42

Page 18: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

CRubyと比べる

・mruby-array-ext gemを入れると

> Array.instance_methods(false).size => 67

Page 19: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mrbgemsを作ってみる

・Arrayクラスにfizzbuzzメソッドを追加する

 gemを作ってみる

・mrubyによる実装と、Cによる実装 

 二つ試す

・https://github.com/ore-public/mruby-fizzbuzz

Page 20: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mrbgemsを作ってみる

mruby-mrbgem-template で作成

http://blog.matsumoto-r.jp/?p=3923

Page 21: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mrbgemsを作ってみる

・ディレクトリ構成mruby-fizzbuzz├── LICENSE├── README.md├── mrbgem.rake├── mrblib│ └── mrb_fizzbuzz.rb   Rubyによる実装

├── mruby-fizzbuzz.gem├── src│ ├── mrb_fizzbuzz.c   C言語による実装

│ └── mrb_fizzbuzz.h└── test └── mrb_fizzbuzz.rb   テスト

Page 22: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mrbgemsを作ってみる

実装のデモ

Page 23: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mrbgemsを作ってみる

・mrubyでも、C言語でも実装出来る

・mrubyの機能で実装出来るものは

 mrubyで作る

・それが無理なものはC言語で作る

Page 24: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mruby内部(mruby-fizzbuzzより)void mrb_mruby_fizzbuzz_gem_init(mrb_state *mrb){ struct RClass *a = mrb->array_class;

mrb_define_method(mrb, a, "fizzbuzz", mrb_fizzbuzz, MRB_ARGS_REQ(1));}

・mrb_state

 mruby起動時に初期化され、mrubyの実行環境の状態を持っている。Objectクラスとか Classクラス Moduleクラスの 実体とか組み込みのクラスのArrayとかString、あとグローバル変数のテーブルとか色々持ってる。

 常に引き回されて、mruby環境の情報をここから取得する。

Page 25: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mruby内部(mruby-fizzbuzzより)include/mruby.h (mrb_stateの一部)typedef struct mrb_state { struct mrb_jmpbuf *jmp;

mrb_allocf allocf; /* memory allocation function */ struct mrb_context *c; struct mrb_context *root_c;

struct RObject *exc; /* exception */ struct iv_tbl *globals; /* global variable table */

struct RObject *top_self; struct RClass *object_class; /* Object class */ struct RClass *class_class; struct RClass *module_class; struct RClass *proc_class; struct RClass *string_class; struct RClass *array_class; struct RClass *hash_class;

Page 26: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mruby内部(mruby-fizzbuzzより)void mrb_mruby_fizzbuzz_gem_init(mrb_state *mrb){ struct RClass *a = mrb->array_class;

mrb_define_method(mrb, a, "fizzbuzz", mrb_fizzbuzz, MRB_ARGS_REQ(1));}

・mrb_define_method

 クラスにメソッドを定義するための関数。

 上記では、mrb_stateからArrayクラスの実体を取得して、”fizzbuzz”というメソッドを定義。

 mrb_fizzbuzzというCの関数へのポインタを渡している。

 rubyの世界で言うと、 [ def ] の実装。

Page 27: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mruby内部(mruby-fizzbuzzより)static mrb_value mrb_fizzbuzz(mrb_state *mrb, mrb_value self){ mrb_int i; mrb_value v, value, fizzbuzz;

value = mrb_ary_new_capa(mrb, RARRAY_LEN(self)); for (i = 0; i < RARRAY_LEN(self); ++i) { v = RARRAY_PTR(self)[i]; if((mrb_fixnum(v) % 15) == 0){ fizzbuzz = mrb_str_new_cstr(mrb, "FizzBuzz"); } else if((v.value.i % 5) == 0) {   (略)

} else { fizzbuzz = v; } mrb_ary_set(mrb, value, i, fizzbuzz); } return value;}

self メソッド呼び出し元のオブジェクトmrb_value mrubyの世界のオブジェクトを格納する型mrb_ary_new_capa Arrayのオブジェクト生成RARRAY_LEN Arrayオブジェクトの長さ取得RARRAY_PTR Arrayに格納されているオブジェクト配列への       ポインタmrb_ary_set Arrayの指定インデックスへオブジェクトのセッ      ト■概要・新規のArrayオブジェクト作成・自分自身の長さ分ループさせて、配列の中身を1つずつ取り 出す・取り出した値がfizzbuzzに該当する値なら、新規Arrayに文 字列オブジェクトをセット・そうじゃなければ、取り出した値をセット

■懸念点・selfがArrayかどうかチェックしてない・selfから取り出した v が整数と決めつけて処理している (別のオブジェクトだった場合、ポインタ値を整数として処   理してるので、落ちずに動いてはいる)

Page 28: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

mruby内部(mruby-fizzbuzzより)typedef struct mrb_value { union { mrb_float f; void *p; mrb_int i; mrb_sym sym; } value; enum mrb_vtype tt;} mrb_value;

■mrb_value構造体

共用体になっていて、float, int, シンボルの値はそのまま valueの中に入っている。

それ以外のオブジェクトは、void *p でオブジェクトへのポインタを持っている。

mrb_vtypeは型の情報を保持。

void型のポインタなので、先のオブジェクトに合わせてキャストが必要だが RARRAY_PTRマクロとかがそれをやってくれている(多分)

fizzbuzzの例では配列の中身が整数(と決めつけて)なので、v.value.i として 整数の値を取得していた。

Page 29: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

まとめ

・mrubyの概要

・mrubyのビルドとmrbgemsについて

・CRubyとの比較(主にArray)・mrbgemの作成(Array#fizzbuzzの実装)

・mrubyの実装を眺める

Page 30: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

今後やってみたいこと

・mrbgemをもっと作る

・コードリーディング

 ・mrubyのAPIのまとめ

・アプリケーションへのmrubyの組み込み

Page 31: Mrubyについて   第16回 岡山ruby, ruby on rails勉強会

参考・RHG (Rubyソースコード完全解説)

 http://i.loveruby.net/ja/rhg/book/・mrubyアドベントカレンダー2013 http://qiita.com/advent-calendar/2013/mruby・Code Reading Wiki http://www.dzeta.jp/~junjis/code_reading/index.php?FrontPage