10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

go-mruby で学ぶ cgo と mruby (1)

Posted at

突然始まった謎のシリーズ。概要をつかむのが主なので不正確だったり読み飛ばしがあります。CとGoとmrubyに関して素人なので、ツッコミはありがたいです。

gomruby.h

まずは唯一のCヘッダファイルから眺める。 static inline で沢山関数も定義されている...。

L24 ~

Go で定義された関数と mruby/C の世界をブリッジするところ。

extern mrb_value *go_mrb_func_call(mrb_state*, mrb_value*, mrb_value*);

extern キーワードを用いると、普通にGoのコード内でCから呼べる関数の中身が書けるっぽい。便利。

static inline mrb_value _go_mrb_func_call(mrb_state *s, mrb_value self)

例外を格納する mrb_value exc を宣言しつつ上記のgo_mrb_func_callをそのまま呼んでいる。

static inline mrb_func_t _go_mrb_func_t() {
    return &_go_mrb_func_call;
}

コメントにある通り、cgoはmrb_valueの共用体であるmrb_func_tをうまく扱えないのでこういうやり方をしているらしい。

go_mrb_func_call は Go の世界で定義される。 https://github.com/mitchellh/go-mruby/blob/master/func.go#L33 の通り、mrubyで呼ばれる処理本体をGoで定義して、その定義されやつらを格納したテーブルからlookupして呼び出すみたいなことをしている。

あとで見ると思うけど _go_mrb_func_t() はGo側でメソッドを定義したら、必ずここを通ることになる。

L54 ~

mruby 側で渡されたメソッド引数をGoの世界に転送するところ。

extern void go_get_arg_append(mrb_value*);

引数である mrb_value を Go の世界にパイプするための入り口。

static inline int _go_mrb_get_args_all(mrb_state *s) {
    mrb_value *argv;
    mrb_value block;
    int argc, i, count;

    count = mrb_get_args(s, "*&", &argv, &argc, &block);
    for (i = 0; i < argc; i++) {
        go_get_arg_append(&argv[i]);
    }

    if (!mrb_nil_p(block)) {
        go_get_arg_append(&block);
    }

    return count;
}

書いてある通り。 mrb_get_args を用いてそのステートの引数とブロックを取得し、
go_get_arg_append に送り込むなどしている。

この辺の処理、むやみにややこしくなっている気がせんでもないんだけど、引数の受け渡しの制御をGoでやった方が並行処理されたときに安全になるみたいな話があるのかな?

L81 ~

こっから先は単純にCでやった方が早いものをCで実装しているだけのようだ。

static inline const char *_go_mrb_calc_send(const char *s)

はポインタ演算をして、

static inline void
_go_mrb_parser_set_capture_errors(struct mrb_parser_state *p, mrb_bool v)

はGoでbit fieladを扱えないのでラップしている、と言う感じっぽい。

L97 ~

あとは、マクロは cgo 経由で呼び出せないので関数と置き換えているところかな?

static inline mrb_aspec _go_MRB_ARGS_ANY() {
    return MRB_ARGS_ANY();
}

static inline mrb_aspec _go_MRB_ARGS_ARG(int r, int o) {
    return MRB_ARGS_ARG(r, o);
}
// ...

そして、続くかは不明なのであった...

10
10
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
10
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?