著作一覧 |
最近仕事ではC#のやたら親切な型チェックに親しんでいるせいで、コンパイル言語で型が違っていてもエラーにならないと、そこはスルーしてしまっていた。
というわけで、Rubyのエンコーディングオブジェクトは、たとえばrb_ascii8bit_encoding()とかで取り出せるわけだが、これがVALUEだと信じ込んでしまっていた。(多分、rb_cObjectなどの仲間のような意識でいたらしい)。エンコーディングを使うのは、rb_external_str_new_with_encとかで(これは便利でtaintなStringをエンコーディング指定でいきなり作れる)、VALUE str = rb_external_str_new_with_enc("foobar", 6, rb_utf8_encoding())というように使うので、ますますVALUEっぽい。でも、実際にはrb_encoding*という型なのであった。
で、おそろしいことに、rb_hash_aset(hash, ID2SYM(rb_intern("encoding")), rb_ascii8bit_encoding())とか書いていたのですな。
当然、それはVALUE(つまりRubyのオブジェクト)ではないのでGCされたりするとその場で死ぬ。
というわけで、rb_encodingをC APIで利用してVALUEにするには、rb_enc_from_encoding(rb_encoding* enc);を呼び出す必要がある(encodingがC API用のrb_encoding*で、encがVALUEという名前っぽい。
ジェズイットを見習え |