« 本当はあまり何もしてくれないDelphi-ObjectiveCブリッジ(メモリ管理編)・・・おまけ | トップページ | CryptoAPI and CNG for Delphi »

2013年5月27日 (月)

本当はあまり何もしてくれないDelphi-ObjectiveCブリッジ(クラスインポート編)

今回は

本当はあまり何もしてくれないDelphi-ObjectiveCブリッジ(クラスインポート編)

です。Windows APIを呼ぶ感覚であんま深く考えないでCocoa APIを呼べるのかなと思ってたのですが、最低限押えておかなきゃいけないことが、結構あるじゃねぇか・・・

ということで、まずは基本的なObjective-Cのクラスのインポートの仕方ですが、既存のインポートの定義を真似ればいいでしょう。例えば、NSString クラスのMacapi.Foundationユニットのインポートは次のようになっています。

見てわかるように、Objective-Cのクラスのクラスメソッド、インスタンスメソッドを定義するDelphiのインターフェース型をそれぞれ用意して、それらを型パラメータとして、TOCGenericImportジェネリッククラスを特化するだけです。

難しくないでしょう。

ちなみに、Objective-Cのクラスのインスタンスメソッドを定義するDelphiのインターフェース型の名前(上記の例ではNSString)で内部でObjecitve-Cのランタイムにクラス情報を問い合わせてるので、ここはインポートするObjective-Cのクラスの名前としっかり合わせておきましょう(もちろん、Case-Sensitiveです)。クラスメソッドを定義するDelphiのインターフェース型の名前(上記の例ではNSStringClass)とTOCGenericImportジェネリッククラスの特化した型の名前(上記の例ではTNSString)は適当でもかまいませんが、ひねくれずに、同じように命名しておけばいいと思います。

また、Delphiのインターフェース型というのは元々、WindowsのCOM(Component Object Model)のインターフェースを扱うために導入されたとの事で、COMのインターフェースを定義する時は、基本的にメソッドの名前よりメソッドを宣言する順番が意味を持ちますが、Delphi-ObjectiveCブリッジでの実装(というより、Objective-Cランタイムでは文字列をベースにしたセレクタというものでメソッドを識別して呼び出す)では、メソッドを宣言する順番は意味を持ちませんが、逆にメソッドの名前(とパラメータの名前)が意味を持ちますので、自分でインポートする時、使用しないメソッドを定義しなくても問題はありません(更に言うと、継承元のインターフェースも別にNSObjectやNSObjectClassである必要もなし・・嘘でした、TOCGenericImportジェネリッククラスの型パラメータにインターフェース型の制約がかかってますね)。

ここまでを踏まえて、次はObjective-Cのオブジェクトのやり取りの仕方を見ていきます。

まずはObjective-Cのオブジェクトへのポインタを入力パラメータとして渡すパターンを見てみます。例えば、NSURL クラスのURLWithStringクラスメソッドを見てみます。

これのMacapi.FoundationユニットのDelphiのインポートの定義を見てます。

入力パラメータの型が対応するDelphiのインターフェース型になってますが、この場合、Delphi-ObjectiveCブリッジの方で自動でDelphiのオブジェクトによってラップされた内部のObjective-Cのオブジェクトのポインタを取り出してくれます。また、次のようにポインタ型で宣言する場合は手動で取り出したりして渡しますが、あえて、こんな面倒な事を誰もしたくないでしょう。

次はObjective-Cのオブジェクトへのポインタを戻り値として返すパターンを見てます。例えば、NSURLクラスのhostインスタンスメソッドを見てます。

これのMacapi.FoundationユニットのDelphiのインポートの定義を見ると、

戻り値の型が対応するDelphiのインターフェース型になってますが、この場合、Delphi-ObjectiveCブリッジの方で自動でDelphiのオブジェクトでラップしてくれますdashdash。ポインタ型で宣言する場合は手動でラップします。

ちなみに、Macapi.Foundationユニットを眺めるとObjective-Cのオブジェクトを戻り値として返すメソッドでも戻り値の型をポイ ンタ型で定義してたり、Delphiのインターフェース型で定義してたりと一貫性がすごく見られないんですけどどういうことなんでしょうかsign02sign02誰か知ってる人がいたら教えて下さいsweat02

で、これで事足りればいいのですが、Cocoa APIを眺めるともう1つパターンがあります。Objective-Cのオブジェクトのポインタを出力パラメータとして返すメソッドです。例えば、NSURLConnection クラスのsendSynchronousRequestインスタンスメソッドを見てみます。

これのMacapi.FoundationユニットのDelphiのインポートの定義を見てます。

とりあえず、第2引数の定義がずっこけてますよねsign02ということで、第3引数と同じように再定義しておきます。

Objective-Cのオブジェクトをポインタとして受け取るように定義したので、いつも通り自分でラップする必要があります。

でも、これだと、いちいちラップするのが面倒なので、戻り値と同じように自動でラップしてもらおうと、例えば、outパラメータを使って、

とDelphiのインターフェース型として定義しても駄目なんですね。現状、戻り値しか自動でラップしてくれません。

というように、中途半端感が拭えなく、本当はあまり何もしてくれないんですdash

うぬぬぬ・・・

ちなみに、これは、エンバカデロによる正式な仕様でもありません。ドキュメントが全くない?ので、Delphi-ObjectiveCブリッジの現状の実装から勝手に読み取ったものですので・・・dashdash

« 本当はあまり何もしてくれないDelphi-ObjectiveCブリッジ(メモリ管理編)・・・おまけ | トップページ | CryptoAPI and CNG for Delphi »

Delphi」カテゴリの記事

MacOS X」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1497665/51735502

この記事へのトラックバック一覧です: 本当はあまり何もしてくれないDelphi-ObjectiveCブリッジ(クラスインポート編):

« 本当はあまり何もしてくれないDelphi-ObjectiveCブリッジ(メモリ管理編)・・・おまけ | トップページ | CryptoAPI and CNG for Delphi »

自作ソフトウェア

無料ブログはココログ

メモ