2009-08-29 10 views
3

J'écris un wrapper autour d'une bibliothèque C en Objective-C. La bibliothèque me permet d'enregistrer les fonctions de rappel lorsque certains événements se produisent.Habillage d'une bibliothèque C avec des pointeurs Objective-C-Function

La fonction register_callback_handler() prend un pointeur de fonction comme l'un des paramètres.

Ma question à vous gourous de la programmation est la suivante: Comment puis-je représenter un appel/sélecteur de méthode Objective-C en tant que pointeur de fonction?

  • Est-ce que NSInvocation serait utile dans cette situation ou à un niveau trop élevé?
  • Serais-je mieux d'écrire simplement une fonction C qui a l'appel de méthode écrit à l'intérieur, puis passer le pointeur à cette fonction?

Toute aide serait formidable, merci.

Répondre

3

Est-ce que register_callback_handler() prend aussi un argument de contexte (void *)? La plupart des API de rappel le font. Si tel est le cas, vous pouvez utiliser NSInvocation assez facilement. Ou vous pouvez allouer une petite structure qui contient une référence à l'objet et au sélecteur, puis concocter votre propre appel.

S'il ne prend qu'un pointeur de fonction, vous risquez d'être arrosé. Vous avez besoin de quelque chose qui identifie le contexte de manière unique, même pour le codage C pur.

Étant donné que votre gestionnaire de rappel ne ont un pointeur de contexte, vous êtes tous ensemble:

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); 

C'est l'idée générale, de toute façon. Si vous avez besoin de traiter des arguments non-objectés et/ou des callbacks, cela devient un peu plus compliqué, mais pas tellement. Le plus simple est d'appeler objc_msgSend() directement après le typecasting à un pointeur de fonction du bon type afin que le compilateur génère le bon site d'appel (en gardant à l'esprit que vous devrez utiliser objc_msgSend_stret() pour les types de retour de structure).

+0

Je ne peux pas divulguer trop d'informations sur la bibliothèque, je ne suis pas autorisé :(Les ​​paramètres sont (XFINST inst, unsp int int, vide * func, void * freedata); Le premier est l'instancem client, le second est un identifiant de paquet pour l'événement particulier, le troisième est le pointeur de la fonction de rappel, et le dernier est un pointeur vers certaines données que vous voudrez peut-être passer à la fonction de rappel – Jasarien

+0

Eh bien, voilà ... vous êtes doré, alors – bbum

+0

Vous voulez dire que je peux utiliser NSInvocation? – Jasarien

Questions connexes