Ruby拡張ライブラリの危なそうな間違いかた

最も多く呼び出されるであろうWindow.draw系のメソッドを、もうちょっとどーにかできないんだろうか、と思っていろいろいじっていた。
省略可能な引数のあるメソッドは引数が配列で渡されるから、はじめにrb_scan_argsをして受け取るわけだが、これはユーティリティ的関数であって、自力でargcで数をチェックして中身を取り出せば随分軽くなる。


で、ふと思ったのだが。
Cで作った拡張ライブラリが提供するクラスのインスタンスは、Cの構造体をラッピングしたようなもので、型情報を持っていない。
Rubyに渡してしまえばVALUE型になっているし、Cに渡されたときは指定の型にキャストされる。
Data_Get_Structマクロでは、ビルトインクラスかどうかだけチェックされて、そうだったら例外が出る。
それっていうのは、Cで作ったクラスのインスタンスなのか、Rubyの組み込み型なのかをチェックしているだけで、Cのインスタンスが「合っているか」をチェックしてくれているわけではない。
ということは、だ。
例えばImageオブジェクトを渡さないといけないところにFontオブジェクトを渡してしまったら、このチェックは働かずに、すり抜けて、Cで無理矢理キャストされて、おかしな動きをするってことか?
ひとつ試してみようか。


試してみた。
結果は、Segmentation faultとなった。
Imageオブジェクトのポインタだと決め付けて動いているから、構造体の中のポインタを使おうとして、おかしなアドレスを参照している。
自分で作ったライブラリだとそういう間違いをしないから気付かないが、こういうのってよく間違えるもんじゃないのかな。
他の人ってどうしてるんかなーって思って、これまたいつも申し訳ないがStar RubyでTextureを渡すところにFontを渡してみたら、devide by zeroとか出てコケた。
ActiveScriptRuby同梱のやつでちょっと古いから、バージョンを0.3.2aにしたらきちんとチェックされて例外になった。
よくわからん・・・ソース覗いてみるか。
あー
こうやってチェックするんかー
こんなんどこに書いてあったんだw


つーことで俺も慌てて直そう。