« 2006年7月 | トップページ | 2006年9月 »

2006.08.28

[rubycocoa-devel:376]可変引数のバグ修正

[rubycocoa-devel:376]。ちょっと前に rubycocoa-talk での議論中に Jonathan が発見したバグを修正。

ruby では、引数が可変のときに Method#arity は負の数を返すのだけど、そこの処理がうまくないために Objective-C 側から Ruby のメソッドを呼び出すとクラッシュした。もちっと詳しく説明すると

  1. Time#now を Objective-C から呼び出し
  2. これは Ruby のオブジェクトなので RBObject#forwardInvocation: が呼ばれる
  3. NSMethodSignature の取得時にこのバグが影響して、メソッドのタイプ情報が "@@:@" (引数 1コあり) になる
  4. 引数を取り出そうとしたときに、実際には引数は渡されていないので、メモリのへんな場所にアクセスしてクラッシュ(これが Jonathan が 「[time now:nil] とすればクラッシュしない」と言っていた理由)

今回の件は直したからいいけど、Objective-C 側からの 可変引数をもつ Ruby のメソッドの呼び出しが今の実装ではできないってことに気づく。逆の Ruby -> Objective-C ができないのは知ってて、それを調べてたときにそんな予感はしてたけどニーズがないのでちゃんと調べてなかった。実際あまりニーズはないと思うけど、true/false のスイッチ系のメソッドは使いたいかもなあ。

この件はいくつか対応策は考えてはみているのだけど、その話はまたこんど。

|

2006.08.27

図解・Rubyのメソッド探索

The Omni Mouth の "Gooffle" というエントリで、Omni Graffle で作成された例として挙げられている Ruby method lookup flow (PDF)。Ruby のメソッド探索のルールについて図解されてるのだけど、こうやって図で見ると思ってる以上にフクザツに見えるな。

|

2006.08.25

[rubycocoa-deve:375] -Wl,-single_module のノロイ、ふたたび

[rubycocoa-devel:375] の話。

今月のはじめごろに svn-trunk のほうのプロジェクトファイルを、Jonathan が古い .pbproj (Project Buidler) から .xcodeproj (Xcode 2.x) に変換してくれたのだけど、--enable-shared なしの ruby では RubyCocoa のテストスクリプトがクラッシュするようになってしまった。

こんなことって前にもあったよなと、あらためて調べ直してみたら、また -Wl,-single_module でやんの。以前は SINGLE_MODULE = NO とビルド設定に追加してやればよかったのだけど、今の Xcode ではこの設定がない(しても無視される)というわけで、デフォルトのリンカオプションの -single_module が設定されてしまうらしい。いろいろあさって、GENERATE_MASTER_OBJECT_FILE = YES とすれば Xcode で同等の結果が得られることがわかったので、そのパッチを送った。

まあそもそも -single_module がつくとなんで問題になるのかはよくわかってないのだけどね。

|

2006.08.22

RubyCocoa を ruby-1.8.5-preview5 でテスト

[ruby-dev:29347] 最後の preview ということなのでテスト。

 Finished in 0.562181 seconds.
 
 89 tests, 213 assertions, 0 failures, 0 errors
 <--- tests
 install.rb: test done.

テストでカバーしている範囲は問題なし。

|

TN2124 は英語のほうも見よう

RubyCocoa の BUG:39 の件に関連して、objc-runtime のコードをながめていたら 環境変数によってデバッグメッセージが出力できるらしいことに気づく。で、ちょっとまとまった情報がないかなと探してみたら、Dave Dribin's blog の "Tracing Objective-C messages" というエントリを見つけた。環境変数 OBJC_HELP を設定して、なんらかの実行ファイルを実行すると、デバッグ出力に関係する環境変数が出力されるのだ。ちなみにこれらの出力は、本当にランタイム内部に関する情報が多いので、普通のアプリケーション開発時にはそれほど威力を発揮しないと思う。OBJC_PRINT_IMAGES くらいかなあ。

つーか、Technical Note TN2124: Mac OS X Debugging Magic にキッチリ書いてあるじゃん!日本語のほうは10.4での更新が反映されてなかったから気づかなかったよ。DYLD_ 系の環境変数は man dyld で知ってたけどさ。とりあえずこのページを "10.4" で検索してチェックしてみたけど、あまり面白いネタはなかった。ただ table 8 の「gdb でのデバッグ時に Objective-C のランタイム関数を使うと便利だよ」てな情報なんかは更新で充実してきたなと感じる。

まあ和訳があるにしろ、一次情報を忘れちゃいけないって教訓?

|

2006.08.19

BUG:39 なにがなにやら

ここ3日くらい、先日の [BUG:39] の調査を続けてるんだけど、さっぱりわからねえ。とりあえず状況だけ整理すると、ruby 側で ns_override または addRubyMethod_withType で定義した ruby のメソッドを Objective-C から呼び出ししたときに、以下の3点の問題があるようだ。

  1. 引数の型が float または double のとき、Objective-C から渡された値が Ruby で正しくとれない
  2. 返値の型が float のとき、Ruby から返された値が Objective-C で正しくとれない
  3. 返値の型が double のとき、Objective-C から呼び出すと、methodSignature の取得のところで落ちる

1. と 2. は同じような理由かもしんないけど、2. にまず焦点を当てて調査。つーか、stuffForwardResult:(RBObject.m) の setReturnValue: した値が正しいところまで確認はしたので、これ以上なす術がないよ。行き詰まってしまったので、とりあえず他のことをしよう。

実験に使ったコードを、いちおうさらしておく。

 #import <objc/objc.h>
 #import <Foundation/Foundation.h>
 
 // dummy class for methodSignature
 @interface FloatX : NSObject
 - (float)testFloat:(float)fl;
 @end
 @implementation FloatX
 - (float)testFloat:(float)fl
 {
   return fl + 1.0;
 }
 @end
 
 @interface Float : NSObject
 //- (float)testFloat:(float)fl;
 @end
 
 @implementation Float 
 /*
 - (float)testFloat:(float)fl
 {
   NSLog(@"%@ %s - %e", self, _cmd, fl);
   return fl + 1.0;
 }
 */
 - (void)forwardInvocation:(NSInvocation *)inv
 {
   if (strcmp((char*)[inv selector], "testFloat:") == 0) {
     //void* arg1;
     //unsigned int buflen = [[inv methodSignature] methodReturnLength]; 
     //NSLog(@"size of %s %d <=> %d", [inv selector], buflen, sizeof(float));
     //arg1 = malloc(buflen);
     void *arg1 = malloc(sizeof(float));
     [inv getArgument:arg1 atIndex:2];
     NSLog(@"%@ %s -(in) %e", inv, _cmd, *(float*)arg1);
     float ret =  *(float*)arg1 + 3.45;
     [inv setReturnValue:&ret];
   } else {
     [super forwardInvocation:inv];
   }
 }
 
 - (NSMethodSignature*)methodSignatureForSelector:(SEL)a_sel
 {
   if (strcmp((char*)a_sel, "testFloat:") == 0) {
     return [FloatX instanceMethodSignatureForSelector:a_sel];
   } else {
     return [super methodSignatureForSelector:a_sel];
   }
 }
 @end
 
 
 int
 main(int argc, const char* argv[])
 {
   id flt;
 
   id pool = [[NSAutoreleasePool alloc] init];
   flt = [[Float alloc] init];
   float f = [flt testFloat:1.23];
   NSLog(@"main - %e", f);
 
   [pool release];
   return 0;
 }

NSInvocation で転送されたメソッドについて、引数および返値が float のとき、NSInvocation で正しく取り扱えていることを確認した。実際には RubyCocoa では、handle_ruby_method_id/stret により 可変引数の形で受け取っているので、引数についてはその形式のメソッドとして va_list からとれるかってことを確認しないとやり方としては正しくないかも。

|

2006.08.18

RubyCococa BUG? double または float を引数にもつメソッド

先週に登録されたバグ。double または float の引数を受け取るメソッドを Ruby 側で定義し、そのメソッドが Objective-C 側から呼ばれたとき問題があるとのこと。現象は添付テストケースで再現したんだけど、まだ原因がつかめず。

いくつかアタリをつけてチェックしてみたところ、objc_msgSendv() でメソッド呼び出ししたときの、va_list のとりまわしがうまくできていない感じ。"Sending floats using objc_msgSendv" と同じような話じゃなかろーか。このケースで marg_* 系のマクロが正しく動作しないらしいので、特殊処理をしないとダメ。ppc は marg_list の構造が Messengers.subproj/objc-msg-ppc.s のコメントに書いてあるから、頑張りゃ対応できるとは思うけど、i386 も同じなのかどうかがわからんのが厳しいなあ。

(調査は継続)

|

2006.08.16

DarwinPorts の rb-gnome が更新された

DarwinPorts あらため MacPorts で rb-gnome(Ruby-GNOME2)が古かったりビルドできなかったりしたので、前にパッチを送った。昨日になって、「パッチ採用したよ、ドウモ」みたいなメールがきた。

確認しようと port sync したところ、0.15.0になってた。送ったのは 0.14.1 なのに…。

|

2006.08.15

Xcode 2.4 のリリースノートがないよ

そういえば、先週 Xcode 2.4 がリリースされたんだけど、リリースノートが 2.3 (2006-05-23) のままなんだよね。更新されてるのって Compiler Tools だけだから、intel 64bit 対応くらいが変更点なのかな?

「x86_64 のファイルについては `strip(1) -x` はなにもしないぜ」とか書いてあるのがちょっとイヤな感じ。シンボルはコンパイル時に削らないといけないのか。

|

2006.08.14

RubyCocoa の apple-unstable ブランチがマージできるか検証

ブランチの寿命は短くしないといけない。これはプロジェクトの原則。そうしないと、コードの維持がどんどん大変になってしまうから。

なので、「apple-unstable ブランチを trunk にマージしないの?」との提案が Laurent から [rubycocoa-devel:347]。まあ当然だよな。とりあえず下調べ。

svn trunk は最近まで手つかずだったのだけど、Jonathan が

  • プロジェクトファイル(フレームワーク, テンプレート, サンプル)の .xcodeproj 化(Xcode 2.1以降用)に変換
  • ビルド設定の一部を外部化(configuration ファイルを利用)

というビルド周りの変更を行ったため、そのまんまではマージできない可能性もある。まあでも、変更部分はそんなにぶつかってないだろうから、svn merge で一発マージできるんじゃないかとちょっと期待して実験。

 % # svn trunk の作業ディレクトリに移動
   # まずはブランチが作成されたリビジョンを調べる
 % svn log --stop-on-copy https://svn.sourceforge.net/svnroot/rubycocoa/branches/apple-unstable/src  
   :
   :
 ------------------------------------------------------------------------
 r981 | (no author) | 2006-05-29 15:25:24 +0900 (月, 29  5 2006) | 2 lines
 
 This commit was manufactured by cvs2svn to create branch
 'apple-unstable'.
 ------------------------------------------------------------------------
 % 
   # というわけで、r981からのすべての変更を trunk にマージするとどうなるかを
   # ファイルを変更せず(--dry-run)に確認する
 % svn merge --dry-run -r981:HEAD https://svn.sourceforge.net/svnroot/rubycocoa/branches/apple-unstable/src 
   :
   :
 %

というわけで、以下の 3ファイルが衝突していることがわかった。

 C    ChangeLog
 C    install.rb
 C    metaconfig

まあコイツらくらいなら、そんな大変ではないんじゃなかろーか、というメールを出した [rubycocoa-devel:354]

|

2006.08.12

RubyCocoa has been included in Leopard!

Laurent の rubycocoa-talk での発言より。というわけで、Leopard に RubyCocoa は入ることが決まってたらしい。

うーん、もうちょっと整理したいとこだけど、前のリリースよりずいぶん良くなってるのは確かだからいいか。

|

RubyCocoa で CoreData をもっとらくちんに

またアイディアだけ。

coredata.rb の OSX::CoreData.define_wrapper 関数で、自動的にエンティティのアクセサメソッドを定義することができる。ただ、これは Ruby 側で NSManagedObject のサブクラスを定義しているときだけだ。NSManagedObject にすべてのエンティティのアクセサを定義してしまうのは、いくらなんでもやりすぎだと思うのだ。

でも、それはそれで不便だ。そのためだけに、サブクラスを定義するのもバカらしいし。

じゃあさ、自動的にサブクラス作っちゃえばいいんじじゃないか?モデル情報をロード〜NSManagedObjectContextに登録、という手続きの最中で、

  1. エンティティのクラスが NSManagedObject のとき、自動的にサブクラスを生成。名称はエンティティを CamelCase 化したものに。
  2. エンティティのクラスを上記で生成したサブクラスに差し替え(モデルを変更)
  3. define_wrapper でアクセサを定義

とすることで実現できるように思える。クラス名をどう決定するかは検討の余地があるけれど、なかなか良さそうだと自分は思う。こういうギミックは好き。

|

irb -r が落ちる件続報

RubyCocoa のバグトラッカーにも入っているこの問題だけど、RubyCocoa には直接関係なくって、いくつかの拡張ライブラリで発生する。[ruby-dev:29253] で上がってたので、またいくつか試してみたら

 % ruby -e '$0 = "foo"; require "osx/cocoa"'
 [BUG] Bus Error

あああー、これだけでダメなのかあ。手を入れられるとしたら、ruby.c の set_arg0() あたり?全然わからん。

(2006.08.14 追記)なかださんの ruby.c へのパッチ [ruby-dev:29261] または [ruby-dev:29264] で、この現象が発生しなくなる。さすがだ。(注:29264はまだ blade にアーカイブされてない)

|

2006.08.10

今日のコミット > RubyCocoa

すべて svn のほうにコミット。

  • Jonathan も賛成してくれたので、引数が不足しているときの例外を ArgumentError に変更
  • 上記変更についてのテストケースを追加
  • ocm_perform() で引数が不足しているかの判定が正しく動作しないバグを修正

例外を発生させる処理が rb_raise() じゃなくて rb_exc_new() なので、書式が使えないのがめんどかった。

|

2006.08.08

転ばぬ先の warn

まだアイディアだけ。

rubycocoa-talk の未読を消化中に、ib_outlet で定義したアウトレットと、もともと Cocoa のクラスがもっているアクセサメソッドの名前が衝突して、期待する動作にならないって話があった。

こういうのって $VERBOSE が設定されてるときには warn でメッセージを出力するようにするといいんじゃなかろうか。デバッグ時はとりあえず -v や -w してみれば状況が詳しくわかるってのは、なかなか良いと思うのだ。

アタマ使うのは、どこがメッセージが必要な場所なのかを見極めることだよな。

|

「Cocoa Life Vol.2」はもうすぐ発売

この週末から、Cocoa勉強会の会誌 第2弾「Cocoa Life Vol.2」が発売になります。という宣伝。「予告なしに変更される可能性があります」とかあるけど、まんまの内容です。つーかもう変えられないし。ちなみに2冊セット割引などはないそうです。

今回は校正したので他の人の原稿もかなり読んだのだけど、今回も狭いところをガシガシ攻めてる感じ。QTKit や PDFKit は HMDT 3rd とびみょうにかぶらない内容になっているはず。

|

RubyCocoa で Cocoa のメソッドの引数が不足しているときどの例外は発生させるべきか?

ようやくリズムがちょっと戻ってきたような。

[rubycocoa-devel:335]の話。以前に、Cocoa のメソッド呼び出し時に引数が不足していると nil を補完して呼び出してしまう機能を廃止した。この機能はハマりポイントになってもメリットが少ないと考えたためだ。で、その際はあまり考えずに OSX::OCMessageSendException を投げるようにしたのだけど、あらためて考えてみると ruby 上で同様の状況のときと同じ ArgumentError を投げたほうがよいのでは?と思うわけ。

なぜかっていうと、呼び出し先のメソッドが Objective-C と ruby のどちらで実装されているかってことは重要ではないから。そんなことを気にして rescue 書くのってなんかおかしいよな、メッセージはメッセージなのだ。

 begin
   obj.some_method(arg1, arg2)
 rescue OSX::OCMessageSendException, ArgumentError # <- why?
   # do something
 end

というわけで個人的には ArgumentError に変更することに完全に傾いてるのだけど、意見とか希望があれば ML かコメントでもお願いします。

他の例外についても調べないとなあ、でも優先度はあまり高くないなあ。

|

2006.08.02

subversion に移行した?

やっとメール読む時間と気力ができたよ。1ヶ月ぶんの未読をだらだらと消化中。

[rubycocoa-devel:316]から、RubyCocoa の開発リポジトリを subversion に移そうぜ〜作ってみたよという流れなんだけど、もう現在は cvs じゃなくて、こっちにコミットしないとダメなのかな?

うーむ、斜め読みではよくわからない。またあとで読み直そう。

|

« 2006年7月 | トップページ | 2006年9月 »