mrubyをCocos2dxに組み込んで使おうとしているのだが、一部動作がおかしいと思われるところがあった。

Cocos2dxでは関数(セレクタ)を登録して、なにかイベントが発生したらコールバックとして呼び出されるという仕組みでできている。これをmrubyから使おうとしたとき、当然コールバックにブロックを使いたいよね。

でイベントが発生したときに、登録されたブロックをC側から呼び出すのだけど、呼び出されたブロック内で同じクラス内のメソッドが呼び出せないという現象が発生した。調べるとselfの値がおかしいということがわかった。mrubyでブロック内のselfの値が戻り値によって壊れるで見たときはmruby内でも壊れることがあったけど、今度はC側から呼び出したときにだけ発生するぽい。

原因を探っていくと、どうやらmrb_yield関数を使うとおかしくなることがわかった。かわりにmrb_funcall関数だと意図した通りに動く。本当ならブロック生成時のselfを使う必要があるんだけど、違うものを渡しているっぽい。

ということでPull requestを投げた。前回調べたときに、レジスタ0がselfを保持していることになっている、ということを学んでいたので、原因さえ特定されてしまえば変更自体は簡単だった。しかしテストコードはRuby上のものしかなくて、こういったまたがるケースは調べてないので、この変更で他を壊していないかどうか不安だ。というか、mrb_yield関数はコード内やmrbgemからほとんど使われてないようだ。