DEV Community

Tomoyuki Sahara
Tomoyuki Sahara

Posted on

1.0.0 でも master でも動く mrbgem の書き方

注: この記事は 2014/03 に書いたものです。

mruby の安定版1.0.0最新版のどちらでも動作する mrbgem の書き方を紹介します。以下では、安定版のことを 1.0.0、最新版のことを master と呼びます。

C 言語 API の変更

mrb_str_cat_lit の追加

mrb_str_cat_lit の動作は mrb_str_cat_cstr と同じです。strlen(3) 一回分速いだけの違いしかありませんから、mrb_str_cat_cstr を使っておけば間違いありません。

mrb_const_defined_at の引数の型の変更

返り値と第二引数の型が異なります。第二引数の型は mrb_valuestruct RClass * でまったく異なるため注意が必要です。

/* master */ mrb_bool mrb_const_defined_at(mrb_state *mrb, mrb_value mod, mrb_sym id);
/* 1.0.0  */ int mrb_const_defined_at(mrb_state *mrb, struct RClass *klass, mrb_sym id);

mrb_class_get の仕様変更

mrb_module_get は 1.0.0 と master の違いの中でもっともひっかかりやすいものです。1.0.0 では mrb_class_get の引数としてクラスもモジュールもどちらも指定できましたが、master ではクラスしか指定できなくなりました。モジュールを得るためには替わりに mrb_module_get を使う必要があります。重要な非互換ですが、対応は容易です。1.0.0 では mrb_module_get は以下のように定義できます。

#if MRUBY_RELEASE_NO < 10000
static struct RClass *
mrb_module_get(mrb_state *mrb, const char *name)
{
  return mrb_class_get(mrb, name);
}
#endif

例: https://github.com/iij/mruby-io/blob/master/src/io.c#L23

mrb_yield_internal の名称変更

mrb_yield_internal は 1.0.0 では非公開な API という位置付けでしたが、便利なためいくつかの mrbgem から利用されていました。master では mrb_yield_with_class と名前を変え、mruby.h で公開されるようになりました。

Ruby 言語処理系としての動作の変更

const_defined? の変更

トップレベルで定義されているモジュール/クラスの名前を Module#const_defined? に与えると、master では true が返ってきます。これは CRuby と同じ挙動です。1.0.0 では false を返してきました。

class A
end
class B
end
p B.const_defined? :A
p B.const_get :A
% mruby a.rb
true
A

% mruby-1.0.0 a.rb
false
A

Float#nan? の追加

Float#nan? は master にはありますが 1.0.0 にはありません。以下のように実装できます。

unless Float.method_defined? :nan?
  class Float
    def nan?
      not (self == self)
    end
  end
end

例: https://github.com/iij/mruby-iijson/blob/master/mrblib/json.rb#L104

Integer#div の追加

Integer#div は master にはありますが 1.0.0 にはありません。以下のように実装できます。あるいは、1.0.0 にもある Integer#divmod を使って回避することも可能です。

unless Integer.method_defined? :div
  class Integer
    def div(other)
      self.divmod(other)[0]
    end
  end
end

または 123.div(45) => 123.divmod(45)[0]

Top comments (0)