3

Objective-C で C ライブラリのラッパーを作成しています。このライブラリを使用すると、特定のイベントが発生したときにコールバック関数を登録できます。

register_callback_handler() 関数は、パラメーターの 1 つとして関数ポインターを取ります。

プログラミングの達人への私の質問は次のとおりです。Objective-C メソッド呼び出し/セレクターを関数ポインターとして表現するにはどうすればよいですか?

  • NSInvocation は、この状況で役立つものでしょうか、それともレベルが高すぎますか?
  • メソッド呼び出しが記述された C 関数を記述し、その関数へのポインタを渡す方がよいでしょうか?

どんな助けでも素晴らしいでしょう、ありがとう。

4

1 に答える 1

3

register_callback_handler()(void*) コンテキスト引数も取りますか? ほとんどのコールバック API がそうです。

そうであれば、NSInvocation を非常に簡単に使用できます。または、オブジェクトとセレクターへの参照を含む小さな構造体を割り当ててから、独自の呼び出しを作成することもできます。

関数ポインタしかとらない場合は、おそらくうんざりしています。純粋な C コーディングの場合でも、コンテキストを一意に識別する何かが必要です。

コールバック ハンドラにコンテキスト ポインタがある場合、準備は完了です

typedef struct {
    id target;
    SEL selector;
    // you could put more stuff here if you wanted
    id someContextualSensitiveThing;
} TrampolineData;

void trampoline(void *freedata) {
    TrampolineData *trampData = freedata;
    [trampData->target performSelector: trampData->selector withObject: trampData-> someContextualSensitiveThing];
}

...
TrampolineData *td = malloc(sizeof(TrampolineData));
... fill in the struct here ...
register_callback_handler(..., trampoline, td);

とにかく、それが一般的な考えです。非オブジェクト型の引数やコールバックを処理する必要がある場合は、少しトリッキーになりますが、それほどではありません。最も簡単な方法は、正しい型の関数ポインターに型キャストした直後に objc_msgSend() を呼び出して、コンパイラーが正しい呼び出しサイトを生成するようにすることです (構造体の戻り値の型には objc_msgSend_stret() を使用する必要がある場合があることに注意してください)。

于 2009-08-29T19:40:58.250 に答える