Обтекание библиотеки C с помощью Objective-C - указатели на функции - PullRequest
3 голосов
/ 29 августа 2009

Я пишу обертку вокруг библиотеки C в Objective-C. Библиотека позволяет мне регистрировать функции обратного вызова, когда происходят определенные события.

Функция register_callback_handler () принимает указатель функции в качестве одного из параметров.

Мой вопрос к вам, гуру программирования, таков: как я могу представить вызов / селектор метода Objective C в качестве указателя на функцию?

  • Будет ли NSInvocation чем-то полезным в этой ситуации или слишком высоким уровнем?
  • Было бы лучше, если бы я просто написал функцию C, в которой был написан вызов метода, а затем передал бы указатель на эту функцию?

Любая помощь будет отличной, спасибо.

1 Ответ

3 голосов
/ 29 августа 2009

Принимает ли 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 () для структурных возвращаемых типов).

...