« 2006年12月 | トップページ | 2007年2月 »

2007.01.31

RubyCocoa 今日のコミット(2007.01.31)

というわけで、objc_alias_method と objc_alias_class_method を実装して、テストコードも足してコミット(r1498)。ひさしぶりだったので svk push 時に verbatim 忘れた。

作業してて思ったこと

  • method_list_alloc() が2つあるのてばどうなの? (objc/OverrideMixin.m と objc/RBClassUtils.m) しかも微妙に型ちがったりするし。
  • String#to_sel とかほしいなあ。次の3パターンくらいか?
    • 文字列のみから変換
    • 型情報つきで変換
    • Ruby のメソッドは実装済み(arity が使える)

そんなに切実ではないので深くは考えてない。

|

2007.01.30

objc_alias_method ほか

ひ日誌の「RubyCocoaでPosingやMethod Swizzlingは可能?」に反応。

Posing

Posing は結構制約が多いし、Swizzling を利用すればサブクラスを利用する必要がほぼないと言える(個人的な経験では)ので、「使わない」という決断をすればよいかと。Ruby 側で定義したサブクラスでは、インスタンス変数が追加されているので Posing はうまく動作しないはず。

Method Swizzling

addRubyMethod: がほぼ同様のことをしているので、実装としては特に障害はないはず。以前に手元の環境で試験的に実装したことあるし。

  • Module#alias_method と同じように Module#objc_alias_method といったところ
  • Cocoa なクラスでは alias_method も再定義して、対象のメソッドが objc 側にもあるかどうかに応じて (オリジナルの)alias_method と objc_alias_method を呼び出す

という感じでどうだろう? 構文のほうの alias はどうしようもないか。数日中にはパッチを ML に投げるつもり。

|

ヒレガス本の第3版が(早ければ)秋くらいに?

Cocoa の入門書として定番とも言える(持ってないけど)ヒレガス本こと「Cocoa Programming for Mac OS X」の第3版が進行中らしい。

MacResearch でのヒレガスへのインタビューによれば、

The third edition Cocoa Programming for Mac OS X will address Objective-C 2, Xcode 3, and Core Data. I'm working on it now, but don't expect it to reach bookstores until autumn.

とのこと。完全に Leopard 対応してくるつもりのようだ。 現在出版されてる邦訳の第1版は、10.2 のころのものなので、この新版の翻訳出ないかなあとハカナイ期待をしてみる。

|

2007.01.29

Cocoa のクラスとバンドルの関係は?

ひ日誌の「Rubyで書いたObjective-Cのクラスはメインバンドルに所属」にコメント書けなかったのでこっちに。

状況としては、Cocoa の中で持ってる、クラスとバンドルファイルのマッピングの関係がうまく登録されてないようだ。いくつかキーワードを試してみて、"objc_addClass" と "bundleForClass" での検索で PyObjC のほうでも同様の問題に遭遇していたらしい ことがわかる。

じゃ、PyObjC ではどうやって解決しているのかっていうと、NSBundle のメソッドをオーバーライドして自前のマッピングにもとづいてクラスの定義された(であろう)バンドルを返すようにしている。

Apple の objc-runtime のコードを読んだ感じでは、mach-o のバンドルファイル(MH_BUNDLE)をロードしたときだけイメージ中のクラスにたいして特殊な処理をしているようだ。objc_addClass() のときには、そういったことはしていないのでメインバンドルになってしまうと。

解決方法としては

  • PyObjC と同じように NSBundle を変更する
  • NSBundle.loadNibNamed_owner_ を使うのはあきらめる

前者かなあ。

|

2007.01.28

RubyCocoa での Objecitve-C から Ruby のクラスメソッドの呼び出し

けっきょく見込みより1週間遅れたし、最近動きが速いようなので、キャッチアップはあきらめ。すべてのメールを既読にしてしまい、興味のあるとこだけコードを確認して、ML のほうにもぼちぼち参戦するような感じで。

で、クラスメソッドがオーバーライドできるようになったそうなので、そこを調べてみることに。知らない人も少なくないと思うのだけれども、RubyCocoa では Cocoa のクラスメソッドをオーバーライドすることができなかっただけではなく、そもそも Objecitve-C 側から Ruby のクラスメソッドの呼び出しができなかったのだ。インスタンスメソッドでは、Objecitve-C の メッセージ転送 を利用している。自分が以前に試したときは、クラスメソッドではこの仕組みが動作しないようだ(NSObject に転送関連のメソッドがクラスメソッドとしても実装はされているが、呼び出されない)ったので、「もう、Objective-C 側に IMP つっこむしかないかなあ」と思っていたのだ。

oc_import.rb の OSX::OCClsWrapper#singleton_method_added では、クラスメソッドのオーバーライドには対応しているものの、そうでないときには Objective-C のランタイム側にはなにもしていない。Ruby 上でメソッドが定義されるだけ。これって非形式プロトコルなんか動くんだろうか。ちょっと疑問。

じゃ、このへんの検証から手を付けることにしよう。つづく。

|

2007.01.27

MacFUSE + Spotlight はどうだろう

ベーパーなアイディアの話ね。

ちょっと前に Google の Amit Singh (Mac OS X Internals の人としても有名) による MacFUSE が公開されたよね。ふつうの fuse として、sshfs なんかも使える(利用できるファイルシステムのリスト)のだけれど、Mac OS X 独自の機能として SpotlightFS なんてのもある。これは、スマートフォルダを fuse を通してファイルシステム化することで Finder 以外でもスマートフォルダが利用できるようになるってものだ。

で、今回言いたいのはそういう Spotlight の利用ではない。ファイルシステム化することで Spotlight のインデックス化ができるようになるんじゃないのか?と思うわけだ。Mail.app が1メールにつき1ファイルになったのは、Spotlight を利用するためと言われているけれども、CoreData アプリケーションなんかでは1ファイルに多数のデータが格納されることも多く、Spotlight に対応したとしても レコードの特定まではできない。

そこでアプリケーションデータを MacFUSE 上に展開させれば、レコードごとに1ファイルとすることができるので、ファイルシステム上のパスと内部のデータを関連づけしておけば、そのファイルへの要求に対してレコード情報を提供することができるわけだ。

新しいファイルシステムを作るには、IBM developerWorks の「FUSEによる独自ファイルシステムの開発」が参考になりそう。

また、Objective-C/Cocoa での実装としては、MacFUSE with Objective-C で公開されている CFileSystem がある。これは CFileSystem クラスのサブクラスをつくることで新しいファイルシステムを作ることができる。Cocoa プログラマ的にはこちらのほうが親しみやすい。

|

2007.01.09

それでも世界は続いていく

年末あたりからマジなんもできてない…。いや、仕事はしてるんだけどさ。

追い上げの開始は(希望的観測で)来週末あたりになる予定。RubyCocoa は 1.0 でちゃいそうだなあ。

|

2007.01.01

RubyCocoa 1.0 Sneak Preview

すでにアナウンスされているように、RubyCocoa 1.0 Sneak Prevew として、0.9.0 がリリースされました。ちょっと遅くなってしまったけれど、紹介ページの翻訳をしておきます。一部超訳です、あしからず。

(以下翻訳)

このページは、将来 1.0 リリース版となる RubyCocoa の unstable branch(訳注:apple-unstable-branch)の現状について説明したものです。

今のところ、まだまだ手をいれているものの、機能的な面はほとんど実装されていますし、安定版リリース(訳注:0.5.0)よりも信頼性があるとさえ言えます。そこで、pre-release 版を試すに当たってのご案内をここで提供します。あなたが見つけたどんな問題についてでも、レポートをいただければ幸いです(訳注:ここ2文超訳)。

Getting Started

最新の pre-release は、0.9.0 です。バイナリのインストーラソースコードの両方が用意されています。

ソースコードをダウンロードした場合は、自分で RubyCocoa をビルドする必要があります。

 $ cd rubycocoa-unstable
 $ ruby install.rb config
 $ ruby install.rb setup
 $ sudo ruby install.rb install

また、Subversion リポジトリから最新のコードを入手することもできます。

 $ svn co https://rubycocoa.svn.sourceforge.net/svnroot/rubycocoa/branches/apple-unstable/src rubycocoa-unstable

RubyCocoa をインストールすると、サンプルが /Developer/Examples/RubyCocoa にインストールされています。

What's New

unstable ブランチでは、多くの修正と改善が行われました。重要な変更について説明します。

Libffi Integration

RubyCocoa でも Libffi が導入されました。"FFI" は Foreign Function Interface の略語です。Libffi は、GCC プロジェクトの一部である C言語のライブラリで、あらゆる C言語の関数を実行することができます。agnostic な方法で(なんだかよくわからない方法で? 適した語を教えてください! - 訳者) 引数を格納、返り値を取り出し、変数の型を抽出することで(関数呼び出しが)実行されます。

RubyCocoa は、2つの世界(訳注:Objective-C と Ruby)間のメッセージ送信において、C 関数や Objective-C のメソッドを Ruby から呼び出しているのに対して、Objective-C からのメッセージ送信では専用の Ruby オブジェクトを経由させています。(訳注:RubyCocoa では、RBObject という Ruby オブジェクトをラップする Objective-C のクラスがあります。このクラスは Cocoa の forward invocation を利用して Objective-C から Ruby メソッドの呼び出しを実装していますが、この機能には、パフォーマンスがあまりよくない、可変引数のメソッドが扱えないなどのデメリットがあります)

RubyCocoa での Libffi の使用は、信頼性とパフォーマンスの向上をもたらしました。RubyCocoa では NSInvocation はもはや利用されていません。

BridgeSupport Metadata

Objective-C の動的性質のおかげで、ブリッジの提供に必要な情報(クラスやそのメソッドなど)は実行時に取得することができます。しかしながら、Objective-C 中の C の部分は動的なものではないために、関数や定数といった C のデータを実行時に知ることはできません。

RubyCocoa では、これらの C の要素を扱うために、ビルド時にヘッダファイルをパースすることにより静的なコードを生成していました。ですが、これは新しいフレームワークのサポートを追加したときに(訳注:RubyCocoa を)再ビルドしなければならないなど、保守性を低下させることにもなってしまいました。ですから、静的なコードではなくメタデータにより Cの要素を扱うというアイディアが実現されました(訳注:この文超訳)。われわれ開発者が用意しておいたメタデータファイルを、RubyCocoa は実行時に解釈します。

メタデータを生成するスクリプトが提供されており、ビルド時にはこのスクリプトによりデフォルトのフレームワークに関するメタデータが生成されます。メタデータファイルは XML 形式で、フレームワークごとに1ファイルとなります。メタデータは、C の関数、enum、定数、構造体、さらには opaque や Core Foudation の型、Objective-C の非定型プロトコルに関する情報を表現します。メタデータは、メソッドの返り値の BOOL 型(訳注:BOOL は内部的に unsigned char で 表現されるため、Objective-C のランタイムから、あるメソッドの返り値が BOOL であるかどうかを判断することができません)や、ポインタ渡しの引数による返り値に関しての情報も提供します。

RubyCocoa は、フレームワークのロード完了後にメタデータファイルを読み込みます。そのため、必要なときだけローカライズされたシンボルを扱うなど、メタデータの寛容な解釈を行うことができます。より多くのフレームワークをサポートすることができるように、メタデータ生成スクリプトは /usr/bin/gen_bridge_metadata としてインストールされます。また、メタデータファイルは /Library/BridgeSupport にインストールされます。

More Frameworks Support

新しいメタデータ機構のおかげで、以前よりも簡単にフレームワークのブリッジを提供することができるようになりました。今までの Foundation, AppKit と WebKit に加えて、unstable ブランチでは CoreFoundation, CoreGraphics, PDFKit, QuartzCore (CoreImage と CoreVideo), OpenGL, QTKit をサポートしています。今後もさらなるフレームワークのサポートを進めていきます。

Syntax Changes

RubyCocoa では、Objective-C のメッセージを Ruby で扱う際に、最後のアンダースコアを省略することができました。これは現在ではサポートされていますが、 OSX.relaxed_syntax の値が false のときには許可されない記法となります。(OSX.relaxed_syntax の初期値は true)

 p OSX.relaxed_syntax                # returns true
 OSX::Array.arrayWithObject('foo')   # OK
 OSX.relaxed_syntax = false
 OSX::Array.arrayWithObject('foo')   # Exception! 
 OSX::Array.arrayWithObject_('foo')  # OK

Ruby から Objective-C にメッセージ送信するときの、symbol / value... という記法は利用できなくなりました。この記法を利用した呼び出しを行う都度、警告が出力され、最終リリース時には例外が発生するようになります。

 OSX::NSURL.alloc.initWithScheme('http', :host, 'www.apple.com', :path, '/macosx')  # BAD
 OSX::NSURL.alloc.initWithScheme_host_path('http', 'www.apple.com', '/macosx')      # GOOD

RubyCocoa では、C の定数を Ruby の OSX モジュールの定数であるかのように扱うことができます。以前のバージョン(訳注:0.4.2まで)では、OSX モジュールのメソッドのようになっていました。OSX モジュールのメソッド形式での定数アクセスは、今後廃止されます。現在では、メソッド呼び出しの都度警告が出力され、最終リリースでは例外が発生するようになります。

 OSX.NSApp    # BAD
 OSX.NSApp()  # BAD
 OSX::NSApp   # GOOD

Support

今のところは、rubycocoa-devel メーリングリストでフィードバックを受け付けています(訳注:日本語での投稿は rubycocoa メーリングリストへお願いします)。バグトラッカーは現在準備中です。

(おわり)

|

« 2006年12月 | トップページ | 2007年2月 »