きりかノート 3冊め

おあそびプログラミング

RubyCocoa 今日あたりのコミット 2013-11-28

ruby-2.0対応の準備とか。

  • 名前が未定義のときModule#nameがruby-2.0ではnilを、1.8では""を返すという差異によるエラーを修正。to_s入れただけ。(r2509)
  • ruby-1.8.4以前用のコードを削除。(r2510, r2511)
  • ruby-2.0でのエラーを修正。requireとeucなファイルへのマジックコメント。(r2512)

OSX.__rebind_umethod__ ってなに?

現時点でruby-2.0でテストを流すと次のエラーがでる。

   "/opt/local/bin/ruby2.0" -I../ext/rubycocoa -I../lib testall.rb
   /.../RubyCocoa.framework/Resources/ruby/osx/objc/oc_import.rb:781:in `__rebi
   nd_umethod__': wrong argument type UnboundMethod (expected Data) (TypeError)
       from /.../RubyCocoa.framework/Resources/ruby/osx/objc/oc_import.rb:7
   81:in `_register_method'

エラーそのものは書いてあるとおりで、__rebind_umethod__の実態であるところのmdl_osxobjc.mの関数にあるようにData_Get_Struct()に渡してるumethodがDataクラスじゃないからダメってこと。ちゅーか逆に、なぜ1.8だと通ってたのかがわからん。

   // FIXME: this is a silly hack.

   struct RB_METHOD {
     VALUE klass, rklass;
     // ...
   };

   static VALUE
   osx_mf_rebind_umethod(VALUE rcv, VALUE klass, VALUE umethod)
   {
     struct RB_METHOD *data;

     Data_Get_Struct(umethod, struct RB_METHOD, data);
     data->rklass = klass;

     return Qnil;
   }

それはそれとして、osx/objc/oc_import.rbの下のほうのObjectいじってるとこと、この__rebind_umethod__がなにをしているかを調べてみた。

RubyCocoaでは、オープンクラス的にObjective-Cのクラスにメソッドを追加することができる。

   module OSX
     class NSData
       def foo(args)
         :
       end
     end
   end

クラスメソッドを呼び出すときなどは、const_missingで処理できるけれど、上記のようなクラス定義のときにはconst_missingでなく新規のクラス定義になってしまう。これをメソッド定義時に強引にクラスを差し替えて実現している。それが上記の__rebind_umethod__での処理になっている。

2.0でこれどうするかって考えると、これはなくしたほうがよいよね。ぜったいヤバそうだし。

に、OSX.ns_importでクラスを実体化してやるってのが妥当な落としどころかなあ。