C++ で継承関係のあるクラスを mruby のクラスとして実装した際のやりかたメモ

mruby-mbed で、mbed の Ticker と Timeout を mrbgems に実装したのでメモ。

mbed の Ticker 、Timeout は下のような継承関係にあるので、mruby-mbed でもそのままこれを実装することにします。

Timeout < Ticker ( < TimerEvent )※TimerEvent は実装しないなので省略

まず、Timeout クラスを定義する際に、mrb_define_class() の第三引数に、スーパークラスとして Ticker クラスを渡します。いらないメソッドは mrb_undef_method() します。

    struct RClass *mrb_mbed_tick;
    struct RClass *mrb_mbed_to;

    mrb_mbed_tick = mrb_define_class(mrb, "Ticker", mrb->object_class);
    MRB_SET_INSTANCE_TT(mrb_mbed_tick, MRB_TT_DATA);
    mrb_define_method(mrb,  mrb_mbed_tick,  "initialize",   mrb_mbed_tick_init,     MRB_ARGS_NONE());
    mrb_define_method(mrb,  mrb_mbed_tick,  "attach",       mrb_mbed_tick_attach,   MRB_ARGS_ANY());
    mrb_define_method(mrb,  mrb_mbed_tick,  "detach",       mrb_mbed_tick_detach,   MRB_ARGS_NONE());

    mrb_mbed_to = mrb_define_class(mrb, "Timeout", mrb_mbed_tick);
    MRB_SET_INSTANCE_TT(mrb_mbed_to, MRB_TT_DATA);
    mrb_define_method(mrb,  mrb_mbed_to,    "initialize",   mrb_mbed_to_init,       MRB_ARGS_NONE());
    mrb_undef_method(mrb,   mrb_mbed_to,    "detach");

そして、メソッドの実装の方で、mrb_obj_classname() で呼び出し元オブジェクトのクラスをみて処理を分ければ OK。例えば Ticker、Timeout のコンストラクタは下の通り。
これでかなり実装が端折れる気がします。

うーん。mruby側でTickerの派生クラス作ったら一発でアウトになったので下のように直した。<2015/04/21 23:51>
これでも共通で使えるメソッドの実装があるのでよしとする。

mrb_value
mrb_mbed_tick_init(mrb_state *mrb, mrb_value self)
{
    DATA_TYPE(self) = &mbed_tick_type;
    DATA_PTR(self) = new TickerThread(new Ticker());

    return self;
}

mrb_value
mrb_mbed_to_init(mrb_state *mrb, mrb_value self)
{
    DATA_TYPE(self) = &mbed_tick_type;
    DATA_PTR(self) = new TickerThread(new Timeout());

    return self;
}