Подтвердить что ты не робот

Создание IMP из блока Objective-C

Тип IMP в Objective-C представляет собой указатель на функцию, насколько я понимаю. Есть ли способ сделать IMP из указателя блока? Спасибо за ваши идеи.

4b9b3361

Ответ 1

Поскольку это было написано, теперь есть API в iOS и Mac OS X, который позволяет Блокам напрямую превращаться в IMP. Я написал сообщение в блоге, описывающее API (imp_implementationWithBlock()).


Блок эффективно представляет собой структуру, которая содержит бит метаданных, ссылку на код, содержащийся в блоке, и копию данных, скопированных с помощью константы, захваченных внутри блока.

Таким образом, нет, нет прямого способа сопоставления между IMP и ссылкой на блок.

Когда вызов блока компилируется, компилятор испускает батут, который устанавливает фрейм стека, а затем переходит к исполняемому коду внутри блока.

Что вы можете сделать, тем не менее, создать IMP, который действует как этот батут. Для следующего вам понадобится один конкретный 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) введите вышеприведенный трамплин для любого селектора через API-интерфейс Objective-C (см. method_setImplementation и т.п.)

Предостережения:

  • это было введено в StackOverflow. Реальный код будет похож, но, вероятно, немного отличается.

  • критика [implementationBlock] имеет решающее значение; Блоки начинают жизнь в стеке (обычно)

Ответ 2

Я считаю, что Майк Эш с некоторой помощью Лэндона Фуллера решил это для общего дела, в том числе iOS, что сложнее. У него есть класс на github, который превратит блок в указатель функции.

Вы также можете пригласить объявление и некоторое интересное последующее обсуждение cocoa -unbound.

ОБНОВЛЕНИЕ: И теперь есть imp_implementationWithBlock(), как указано выше.