Objective-CブロックからIMPを作成する
質問
Objective-Cの IMP
タイプは、私が理解している限り、関数ポインターを表します。ブロックポインターから IMP
を作成する方法はありますか?あなたのアイデアをありがとう。
解決
これが書かれて以来、iOSとMac OS Xには、ブロックを直接IMPに変換できるAPIがあります。 ウェブログの投稿を書きましたAPI(imp_implementationWithBlock())。
ブロックは、実質的に、メタデータの一部、ブロック内に含まれるコードへの参照、およびブロック内でキャプチャされたconstコピーされたデータのコピーを含む構造です。
したがって、いいえ、 IMP
とブロック参照を直接マッピングする方法はありません。
ブロックの呼び出しがコンパイルされると、コンパイラーはスタックフレームを設定するトランポリンを出力し、ブロック内の実行可能コードにジャンプします。
ただし、できることは、そのトランポリンのように動作するIMPを作成することです。以下の場合、引数のセットごとに1つの特定のIMPが必要になります&呼び出される型を返します。これをジェネリックにする必要がある場合は、アセンブリを使用する必要があります。
このため、クラスのインスタンスごとに一意のブロックインスタンスを設定しています。すべてのインスタンスで機能する汎用ブロックが必要な場合は、 SEL
のハッシュを作成します->クラスごとにブロックします。
(1)関連する参照メカニズムを使用して、IMPとして機能するブロックを関連付けます。次のようなもの:
void (^implementingBlock)(id s, SEL _c, int v) = ^(id s, SEL _c, int v) {
// do something here
}
objc_setAssociatedObject(obj, SELToImp, [implementingBlock copy]));
(2)次のようなトランポリンIMPを実装します。
void void_id_sel_intTramp(id self, SEL _cmd, int value) {
int (^block)(id s, SEL _c, int v) = objc_getAssociatedObject(self, _cmd);
block(self, _cmd, value);
}
(3)上記のトランポリンをObjective-CランタイムのAPIを介してセレクターに挿入します( method_setImplementation
などを参照)
警告:
-
これはStackOverflowに入力されました。実際のコードは似ていますが、わずかに異なる可能性があります。
-
[implementingBlock copy]は重要です。ブロックはスタックでのライフを開始します(通常)