LoginSignup
56
53

More than 5 years have passed since last update.

Mac OS Xで、自作プログラムにmrubyを組み込み、C言語からrubyスクリプトを実行させ、rubyからC言語の関数を呼び出す

Last updated at Posted at 2013-06-26

組み込み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.ソース

全体のソースは、こうなっています。

mruby_oka.c
#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言語という順番で呼び出されています♪

56
53
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
53