組み込みrubyです。自作プログラムにmrubyを組み込みます。mrubyからCの関数を呼び出せるようにしておけば、自作プログラムをrubyで拡張できるようになります♪
「Mac OS Xでmrubyをビルドしてみる」でインストールしたmrubyを使います。ビルド時のパスに気を付けてください。
1. rubyから呼び出されるメソッドを用意する
まずは、rubyから呼び出されるメソッドを用意しましょう。今回はサンプルなので、パラメータ無し、戻り値無し、文字を表示するだけのメソッドです。
// この関数を、Okaモジュールに追加し、ruby側から呼び出される関数
static mrb_value oka_func(mrb_state *mrb, mrb_value self) {
puts("This is oka_func!") ;
}
見ての通り、mrb_value
型を返す、oka_func
という名前の関数です。パラメータは2つあり、1つはmrb_state*
型、もう一つはmrb_value
型です。
2. C言語でmrubyを動かす
2.1. mrb_open()
最初にmrb_open()
します。
mrb_state *mrb ;
mrb = mrb_open() ;
mrubyの実行環境は、このmrb_state
の中に入っているようです。これは、単なる構造体なので、複数の変数を用意すれば、それぞれ互いに独立したmruby実行環境となるようです。
2.2. モジュールの定義
mrbに対して、Okaモジュールを追加します。
struct RClass *mdlOka ;
mdlOka = mrb_define_module(mrb, "Oka") ;
これで、Okaモジュールが追加されました。でもまだメソッドが何もありません。追加しましょう。
2.3. メソッドの追加
Okaモジュールが追加されているmrbに、1.で定義したoka_func()
を追加します。
mrb_define_class_method(mrb, mdlOka, "oka_func", oka_func, ARGS_NONE()) ;
2.4. rubyスクリプトを用意する
では、Okaモジュールのoka_func()メソッドを呼び出すrubyスクリプトを、C言語の文字列として用意しておきましょう。
今回はサンプルなので文字列をC言語プログラムに埋め込みますが、この部分をファイルから読み込みようにすれば、自プログラムをrubyスクリプトでカスタマイズできるようになるわけです♪
cosnt char* code = "Oka.oka_func()" ;
2.5. 実行する
あとは、動かすだけです。
mrbc_context *c = mrbc_context_new(mrb) ;
struct mrb_parser_state* st = mrb_parse_string(mrb, code, c) ;
int n = mrb_generate_code(mrb, st) ;
mrb_pool_close(st->pool);
mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_nil_value()) ;
3.ソース
全体のソースは、こうなっています。
#include <mruby.h>
#include <mruby/proc.h>
#include <mruby/compile.h>
// この関数が、Okaモジュールに追加される
static mrb_value oka_func(mrb_state *mrb, mrb_value self) {
puts("This is oka_func!") ;
}
int main() {
// ruby script
const char* code = "Oka.oka_func()";
// mrubyの準備
mrb_state* mrb = mrb_open() ;
// `Oka`モジュールの定義
struct RClass *mdlOka = mrb_define_module(mrb, "Oka") ;
// 'oka_func()'メソッドを'Oka'モジュールに追加
mrb_define_class_method(mrb, mdlOka, "oka_func", oka_func, ARGS_NONE()) ;
// 実行!
mrbc_context *c = mrbc_context_new(mrb) ;
struct mrb_parser_state* st = mrb_parse_string(mrb, code, c) ;
int n = mrb_generate_code(mrb, st) ;
mrb_pool_close(st->pool);
mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_nil_value()) ;
mrb_close(mrb);
}
4.ビルド
$ gcc -I../Downloads/mruby-master/include mruby_oka.c ../Downloads/mruby-master/build/host/lib/*.a -lm -o mruby_oka.exe
「Mac OS Xでmrubyをビルドしてみる」でインストールしたmrubyを使っているので、上記のようなパスを指定しています。ご自身の環境に会わせてパスを書き換えてください。
※ 自分で作成した実行ファイルは、拡張子にexeを付けるようにしています、Mac OS上やLinux上では。
5. 実行
できあがったmruby_oka.exeを実行します。
$ ./mruby_oka.exe
This is oka_func!
$
これで、oka_func()が実行されているのがわかります。oka_func()は、文字列埋め込みしたrubyスクリプトから呼び出されています。rubyスクリプトはmain()の中で実行しています。
つまり、C言語→rubyスクリプト→C言語という順番で呼び出されています♪