bcscanをビルドして動かしてみたら'stack level too deep'と言われた
RubyCocoaの開発ができる状態になったので、下記からbcscan*1のソースを取ってきてビルドしてみた。
とりあえずビルドはできたが、実行してみると下記のようなエラー出てしまった。
[Session started at 2008-09-24 23:25:17 +0900.] /Library/Frameworks/RubyCocoa.framework/Versions/A/Resources/ruby/osx/objc/oc_attachments.rb:1723:in `size': stack level too deep (SystemStackError) from /Library/Frameworks/RubyCocoa.framework/Versions/A/Resources/ruby/osx/objc/oc_attachments.rb:1723:in `count' from /Library/Frameworks/RubyCocoa.framework/Versions/A/Resources/ruby/osx/objc/oc_attachments.rb:1723:in `size' from /Library/Frameworks/RubyCocoa.framework/Versions/A/Resources/ruby/osx/objc/oc_attachments.rb:1723:in `count' from /Library/Frameworks/RubyCocoa.framework/Versions/A/Resources/ruby/osx/objc/oc_attachments.rb:1723:in `size' from /Library/Frameworks/RubyCocoa.framework/Versions/A/Resources/ruby/osx/objc/oc_attachments.rb:1723:in `count' from /Library/Frameworks/RubyCocoa.framework/Versions/A/Resources/ruby/osx/objc/oc_attachments.rb:1723:in `size' from /Library/Frameworks/RubyCocoa.framework/Versions/A/Resources/ruby/osx/objc/oc_attachments.rb:1723:in `count' from /Library/Frameworks/RubyCocoa.framework/Versions/A/Resources/ruby/osx/objc/oc_attachments.rb:1723:in `size' ... 6829 levels... from /opt/local/lib/ruby/1.8/optparse.rb:1334:in `permute!' from /opt/local/lib/ruby/1.8/optparse.rb:1355:in `parse!' from /Users/snaka/work/bcscan-0.1/build/Release/bcscan.app/Contents/Resources/command.rb:27:in `command_init' from /Users/snaka/work/bcscan-0.1/build/Release/bcscan.app/Contents/Resources/rb_main.rb:21 bcscan はステータス 1 で終了しました。
どうもObject-CのNSArrayの拡張クラスの中でcountメソッドとsizeメソッドがお互いに呼び合ってループしているように見える。とりあえず、ループする原因はoc_attachments.rbに問題がありそうだが、よくわからないので別の切り口から回避方法を探ることにした。
まず、エラーが発生の発端となっている、command.rb を見てみる
parser.parse!(args)
ここは単にコマンドラインパラメタを解析しているはずの箇所。parserとはOptionParserクラスを指しているはずで、渡される値も単純な Ruby の配列オブジェクトだと思われる。それなのに、Object-CのNSArrayクラスとして処理が行われている点が怪しい。
ということでargsの値を設定している箇所を調べてみる。そうすると以下のように記述されている。
args = OSX::NSProcessInfo.processInfo.arguments.collect {|arg| arg.to_s}
おそらく、ここで args の値としては Ruby の配列(Array)を期待しているはずだが、実際は Object-CのNSArrayオブジェクトになっちゃてるんじゃないか... と推測。それを検証するため以下のように puts を追加してみた。
args = OSX::NSProcessInfo.processInfo.arguments.collect {|arg| arg.to_s} puts "*** #{args.class}"
で、実行...
*** OSX::NSCFArray
やはり NSArray になっている。これをRubyの配列に戻してあげれば正しく動くはず。以下のよう修正してみた。
args = OSX::NSProcessInfo.processInfo.arguments.collect {|arg| arg.to_s} args = args.to_a
ビンゴでした。たぶん、RubyCocoaの仕様が変ったとかの理由なんだろうな... ということでとりあえずオK