Я ищу способ заставить 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
}
Я проверил, что и собственное Я, и правильный ИМП являются правильными вещами до JMP, и параметр _cmd
также входит правильно. (другими словами, я правильно добавил этот метод).
Однако что-то происходит. Я иногда ловлю себя на том, что прыгаю к методу (обычно не правильному) с nil self
и _cmd
. В других случаях я просто потерплю неудачу с EXC_BAD_ACCESS. Идеи? (я давно ничего не делал в сборке ...) Я тестирую это на x86_64.