†2012/9/9にMobiRubyがリリースされました。いうわけでMobiRubyを読むことにします。Cの関数をRubyから呼び出すためのライブラリであるmruby-cfuncから読解を始めます。「MobiRubyってどこから読み始めればいいのかわからない」とつぶやいたところ、増井さんから「mruby-cfuncとmruby-cocoaのtestからどうぞ」とのお返事をいただきました。いうわけで、test/main.cから読解を開始します。test/main.cのうち、main()は以下のようになっています。}}mrb_stateはmrubyの実行情報を格納する構造体です。mrb_stateにはudという追加情報へのポインタが含まれており、mruby-cfuncの追加情報を格納するのに使用されていることがわかります。cfunc_state_offsetはudで指定している構造体中のcfunc_state構造体のオフセットを表すグローバル変数です。mruby-cfunc中ではこの情報が使われるのでinit_cfunc_module()を呼び出す前に設定する必要があります。†init_cfunc_module()にてmruby-cfuncの初期化が行われます。条件コンパイルになっていますがデフォルトはオフなのでその部分は省いて載せます。init_cfunc_rb(mrb);}というわけで、型、ポインタ、構造体、クロージャ、呼び出しについて初期化が行われるようです。†CFunc::TypeをスーパークラスとしたC(libffi)の型を表現するクラスの定義を行っています。関数ポインタとマクロ、必要情報の埋め込みを使うことで型ごとに必要となる定義をコンパクトにまとめています。double)};と各型について変換に使う関数を関数ポインタとして設定することで記述量を最小化しています。上記で定義した情報を各型クラスにインスタンス変数*1として持たせておくことでinitialize等もスーパークラスのTypeに対して定義したものだけで動くようになっています。initializeは長いのでvalueの実装関数であるcfunc_type_get_value()を載せます。†Cのポインタを表現するCFunc::Pointerの定義を行っています。特筆することはありません。†Cの構造体を表現するCFunc::Structの定義を行っています。cfunc_struct.cに書かれているのはRubyでCの構造体を定義するためのメソッドの実装関数のみです。他のメソッドは?という疑問は後で説明します。次はクロージャを表現するCFunc::Closureの定義です。Cで言うクロージャとは関数ポインタのことです。正確にはクロージャは自分が定義されているスコープの変数を参照できるので関数ポインタとはちょっと違いますが。Rubyで定義したクロージャをCの関数に関数ポインタとして渡すことを実現するための仕組みです。次にCの関数を呼び出すCFunc::callを定義しています。最後にinit_cfunc_rb()が呼び出されています。このinit_cfunc_rb()ですが、grepしてもヒットしません(ビルド前の場合)。実はinit_cfunc_rb()はsrc/mrb/cfunc_rb.rbをコンパイルすることで作られます。そのからくりは、以下のようになっています。$@というわけでビルドプロセスとしてsrc/mrb/cfunc_rb.rbがコンパイルされてCコードになり、init_cfunc_rb()という関数が作られます。cfunc_rb.rbでは既存クラスのmruby-cfunc向けの拡張、Rubyで書かれたmruby-cfuncの追加メソッドが記述されています。先ほどのCFunc::Structのメンバーアクセスメソッドとかもcfunc.rbに記述されています。†mruby-cfuncの初期化が終わったので次は使い方の方を見ていきます。init_cfunc_test()はmruby-cfuncの使い方サンプルになっています。init_cfunc_test()の元はtest/mrb/cfunc_test.rbです。以下のように書きます。CFunc::Int[10]と書けた方がうれしいです。request送ってみるか。以下のように書きます。以下のように書きます。strcpyの戻り値は実際にはchar*ですが戻り値が必要ないならvoidにしてもいいようです。以下のように書きます。:zend個人的にはやや気に食わない。:z)と定義できた方がうれしいです。型と名前の間の","が気に食わないけど仕方ないかな。以下のように書きます。