背景: 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 のリファレンス マニュアルのほこりを払い、アセンブラの錆を落とす時が来たと思います...