Я ищу способ сделать NSInvocation
вызовом определенного IMP
. По умолчанию он вызывает «самый низкий» IMP
, который может найти (т. е. самую последнюю переопределенную версию), но я ищу способ заставить его вызывать IMP
из более высокого уровня в цепочке наследования. IMP
, который я хочу вызвать, определяется динамически, иначе я мог бы использовать ключевое слово super
или что-то в этом роде.
Моя мысль состояла в том, чтобы использовать механизм -forwardInvocation:
для захвата сообщения (простой и уже работающий), а затем изменить IMP
так, чтобы он перешел к методу, который не является ни реализацией super
, ни реализацией самого дальнего потомка. (жесткий)
Единственное, что я нашел, что отдаленно близко, это AspectObjectiveC, но для этого требуется libffi, что делает его не -совместимость с iOS. В идеале я бы хотел, чтобы это была кросс-платформа.
Любые идеи?
отказ от ответственности: я просто экспериментирую
Опробовать идею @bbum о функции батута
Так что я думаю, что у меня в основном все готово; У меня есть следующий батут, который правильно добавляется через class_addMethod()
, и он действительно вводится:
id dd_trampolineFunction(id self, SEL _cmd, ...) {
IMP imp = [self retrieveTheProperIMP];
self = [self retrieveTheProperSelfObject];
asm(
"jmp %0\n"
:
: "r" (imp)
);
return nil; //to shut up the compiler
}
Я убедился, что и правильное self, и правильный IMP являются правильными вещами до JMP, и параметр _cmd
также входит правильно. (другими словами, я правильно добавил этот метод).
Однако что-то происходит. Иногда я ловлю себя на том, что перескакиваю к методу (обычно не правильному) с нулевыми self
и _cmd
. В других случаях я просто падаю в глуши с EXC_BAD_ACCESS. Идеи? (давно я ничего не делал на ассемблере...) Тестирую на x86_64.