mrubyでのありがちなミス4つ

よくやってしまう+これからもやってしまうこと。
(2014/4/28追記:1つめにmruby-clang-plugin紹介)
(2014/4/6追記:4つめ)

mrb_funcall()の可変引数部分は全部mrb_valueじゃないといけない。

ついついintなどをそのまま突っ込んじゃう。可変引数なので何を入れてもコンパイルできちゃう。けど動かない。以下使ってmrb_valueにしてから使う。

  • mrb_fixnum_value()
  • mrb_float_value()
  • mrb_str_new_cstr()/mrb_str_new_lit()

([twitter:@take_cheeze]さんのmruby-clang-pluginを使えばclang使ってコンパイル時にチェックできるぽいです。自分はまだ試せてない。。)

RSTRING_PTR()はNULL終端とは限らない。

mrb_valueの中身が文字列の場合にRSTRING_PTR()使ってchar *取り出せるけどNULL終端とは限らない。printf()に渡して死ぬ。NULL終端が欲しい場合は

  • RSTRING_LEN()で長さを把握して使う
  • mrb_str_to_cstr()でNULL終端文字列を新たに作る。内部で新たにオブジェクトが作られるのでメモリ気にするときは注意。
そもそも普通のRubyプログラムとして間違ってる。

思った通り動かない!なんで?なんで?→単にRubyとして間違ってることがまれによくある。落ち着いてCRubyで検証する。

マクロ定義(MRB_XXX)のミスマッチ

build_config.rbでconf.cc.definesにMRB_WORD_BOXINGとか追加したのに、mrubyを使うプログラム側をコンパイルするときに-DMRB_WORD_BOXING追加するのを忘れてmrb_open()が落ちる/止まる。

使えるMRB_XXXXはinclude/mrbconf.hにあって、全部が全部使う側のプログラムでも指定しないと問題になるわけではないけど、MRB_WORD_BOXING, MRB_USE_FLOAT,MRB_NAN_BOXING,MRB_ENDIAN_BIGあたりは根幹となるmrb_value構造体のレイアウトが変わったりするので特に注意。それ以外も今後変わる可能性があるので基本全部合わせるべき。

自分の場合はメモリ節約しようとして試行錯誤しているうちにbuild_config.rbと使う側のMakefileを合わせるのを忘れて「mrb_open()が返ってこない。メモリ足らない?いやまだ足りてるはず」とかでハマる。

この辺は色々議論もされてるみたいなので改善されていきそう。でもbuild_config.rbはRubyで書けるし、自動生成してもいいし、自分でも工夫できる。