59

背景: CamelBones は Perl クラスを Objective-C ランタイムに登録します。これを行うには、すべての Perl メソッドが同じ IMP 関数に登録されます。その関数はself&_cmd引数を調べて、呼び出す Perl メソッドを見つけます。

これは、 でディスパッチされたメッセージに対して、数年間十分に機能していますobjc_msgSend。しかし今は、Perl メソッドから浮動小数点型と大きな構造体型を返すためのサポートを追加したいと考えています。浮動小数点は難しくありません。でディスパッチされたメッセージを処理するために、単純に double を返す別の IMP を作成しますobjc_msgSend_fpret

問題は、どうするかですobjc_msgSend_stret。可能性のある構造体の戻り値の型ごとに個別IMPに記述することは、次の 2 つの理由から非現実的です。1 つ目は、コンパイル時に既知の構造体の型に対してのみ記述したとしても、それはばかげた数の関数になるためです。次に、任意の Objective-C および Perl コードに対してリンクできるフレームワークについて話しているため、フレームワークがコンパイルされているときに、すべての潜在的な構造体型を把握しているわけではありません。

私がやりたいことは、IMP経由でディスパッチされた戻り値の型を処理できるシングルを書くことobjc_msgSend_stretです。古いが宣言されたように、 returnとして記述voidし、リターン バッファーへのポインター引数を取ることができますか? objc_msgSend_stretそれがたまたま今のところうまくいったとしても、今後もうまくいくと期待できますか?

アドバイスをありがとう-私はこれについて頭を悩ませてきました。:-)

アップデート:

以下は、Apple のランタイム エンジニアの 1 人から、objc-language メーリング リストで受け取ったアドバイスです。

このケースを処理するには、アセンブリ コードを記述する必要があります。

あなたの提案は、「最初の引数として構造体へのポインターを使用して void を返す関数」の ABI が「構造体を返す関数」と異なる一部のアーキテクチャでは失敗します。(i386 では、構造体アドレスは、ある場合には呼び出し元によって、別の場合には呼び出し先によってスタックからポップされます。) のプロトタイプ objc_msgSend_stretが変更されたのはそのためです。

アセンブリ コードは、構造体の戻りアドレスをキャプチャし、残りのパラメーターを乱すことなく非構造体の戻り値の C 関数呼び出しに密輸し、終了ret $4 時に (i386 で) 適切な ABI 固有のクリーンアップを実行します。または、アセンブリ コードですべてのパラメーターを取得することもできます。転送機構は次のようなことを行います。手法がどのように見えるかを確認したい場合は、そのコードがオープンソースの CoreFoundation に含まれている可能性があります。

誰かがより良いアイデアをブレインストーミングする場合に備えて、この質問は開いたままにしますが、これは Apple 自身の「ランタイム ラングラー」から直接得られたものであり、おそらく私が得る可能性が高いのと同じくらい信頼できる答えだと思います. x86 のリファレンス マニュアルのほこりを払い、アセンブラの錆を落とす時が来たと思います...

4

1 に答える 1

5

Appleのエンジニアは正しいようです。進むべき道はアセンブリコードだけです。始めるためのいくつかの有用な指針は次のとおりです。

  • Objective-Cランタイムコードから:さまざまなメッセージングメソッド用のi386およびx86_64手作りメッセンジャーアセンブリスタブ。
  • ディスパッチの概要を提供するSO回答。
  • アセンブリコードの行ごとの分析によるディスパッチングメカニズムの詳細なレビュー

それが役に立てば幸い。

于 2011-05-23T07:48:23.720 に答える