Использование method_getReturnType для вызова определенных типов функций-членов экземпляра

Я новичок в Objective-C, поэтому не очень разбираюсь в этом языке.

То, что я пытаюсь сделать, это просмотреть все доступные методы экземпляра объекта и вызвать те, которые не принимают аргументов, возвращают bool и начинают со строки «func».

Вот как я получаю методы:

uint32_t methodCount = 0;
Method * methods = class_copyMethodList(object_getClass(self), &methodCount);

Я перебираю методы и, когда указанное выше условие соответствует, пытаюсь их вызвать:

NSString * methodName   = [NSString stringWithUTF8String:sel_getName(method_getName(method))];

char retTyp[10];
method_getReturnType(method, retTyp, 10);

const char * desiredRetType = "B";

if([methodName hasPrefix:@"func"] &&
   (0 == strncmp(retTyp, desiredRetType, strlen(desiredRetType))) &&
   (2 == method_getNumberOfArguments(method)))
{
     bool * (* testMethod) (id, Method) = (void (*) (id, Method, ...)) method_invoke;
     result = testMethod(self, method);
}

Мне пришлось экспериментально выяснить, что такое строка типа возвращаемого значения (оказывается, «B» для bool) и количество аргументов.

Я получаю следующую ошибку в строке, где я пытаюсь вызвать функцию с помощью method_invoke:

cannot initialize a variable of type 'bool *(*)(__strong id, Method)' (aka 'bool *(*)(__strong id, objc_method *)') with an rvalue of type 'void (*)(__strong id, Method, ...)' (aka 'void (*)(__strong id, objc_method *, ...)'): different return type ('bool *' vs 'void') 
  1. Есть ли лучший способ сделать это, чем class_copyMethodList?
  2. Как мне правильно привести функцию, чтобы не получить ошибку?
  3. Возможно ли, что преобразование возвращаемых типов методом method_getReturnType() может меняться от системы к системе? Или это всегда B для bool?

person Virag Doshi    schedule 16.02.2019    source источник
comment
Откуда взялся method_invoke?   -  person jscs    schedule 16.02.2019
comment
На 3 технически да, но практически нет.   -  person jscs    schedule 16.02.2019
comment
method_invoke получен от Apple. Что касается 3, не могли бы вы уточнить?   -  person Virag Doshi    schedule 16.02.2019
comment
Конечно. Кодировки определяются компилятором: stackoverflow.com/questionsS/11527385, но они также используются средой выполнения. Поэтому их нужно синхронизировать. Таким образом, у вас может быть пара компилятор/среда выполнения, определяющая их как какие угодно, но программы, работающие в этой паре, будут несовместимы с любой другой средой выполнения. Таким образом, на данный момент кодировки являются своего рода ipso facto ABI.   -  person jscs    schedule 16.02.2019


Ответы (1)


НВМ, я разобрался. Вместо использования method_invoke для имени метода я сделал следующее:

NSString * methodName   = [NSString stringWithUTF8String:sel_getName(method_getName(method))];

char retTyp[10];

method_getReturnType(method, retTyp, 10);
const char * desiredRetType = "B";

if([methodName hasPrefix:@"func"] &&
   (0 == strncmp(retTyp, desiredRetType, strlen(desiredRetType))) &&
   (2 == method_getNumberOfArguments(method)))
{
    SEL testMethod = method_getName(method);
    return [self performSelector:testMethod];
}
person Virag Doshi    schedule 16.02.2019
comment
Это все еще неправильно. Вы должны использовать method_getImplementation() и привести результат указателя функции THAT для безопасного вызова метода. -performSelector: это У.Б. если сигнатура функции не -(id) func, которая в вашем случае возвращает BOOL. Вероятно, это сработает, но может вызвать проблемы в будущем. - person Richard J. Ross III; 23.02.2019