Слишком много аргументов для вызова функции, ожидается 0, есть 2 - PullRequest
1 голос
/ 26 сентября 2019

В прошлом году мы перешли с Pixate на StylingKit

https://github.com/StylingKit/StylingKit, форк Pixate, который, насколько я могу судить, все еще разрабатывается.

Однако у нас есть проблемытеперь с выпуском XCode 11, в pior-версиях он работал просто отлично, но теперь не скомпилируется.

    void* callSuper0(id self, Class superClass, SEL _cmd)
    {
        struct objc_super super;
        super.receiver = (__bridge void *)self;
        super.class = superClass != NULL ? superClass : class_getSuperclass(object_getClass(self));
        return objc_msgSendSuper(&super, preprocessSEL(_cmd));
    }

return objc_msgSendSuper(&super, preprocessSEL(_cmd));

Выдает ошибку "Слишком много аргументов для вызова функции, ожидается 0,иметь 2 "

Я попытался изменить некоторые параметры здания, как показано в https://code -examples.net / ru / q / 17c4b21 , в частности" Включить строгую проверку вызовов objc_msgSend для NO ", но этоне помогло

Буду признателен за любую помощь.

Ответы [ 2 ]

1 голос
/ 26 сентября 2019

Примечание: приведенный ниже код не был выполнен, так как он является просто фрагментом, однако он был скомпилирован Xcode 10 и 11. Возможны ошибки или другие проблемы.

В XCode щелкните правой кнопкой мыши на objc_super и objc_msgSendSuper и выберите «Перейти к определению», что откроет системные файлы, содержащие определения.Это покажет две вещи:

  1. Имена полей, и типы objc_super изменились с момента написания вашего кода, некоторые из них описаны в комментариях.
  2. Прототип дляobjc_msgSendSuper также изменился до void objc_msgSendSuper(void), предыдущий прототип тоже там id _Nullable objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...).Используя предыдущий прототип, вызов этой функции в коде может быть выполнен без приведения, с этим новым прототипом требуется приведение.

Внесение изменений, указанных в коде, дает:

// A typedef for objc_msgSendSuper which takes only the required (first two) arguments
typedef void *(*NoAdditionalArgMsgSendSuper)(struct objc_super *super_class, SEL selector);

void* callSuper0(id self, Class superClass, SEL _cmd)
{
   struct objc_super super;
   // .receiver is now defined as "__unsafe_unretained _Nonnull id" so no bridge cast required
   super.receiver = self;
   // .super_class is new name for .class
   super.super_class = superClass != NULL ? superClass : class_getSuperclass(object_getClass(self));
   // cast objc_msgSendSuper to the correct type and then call
   return ((NoAdditionalArgMsgSendSuper)objc_msgSendSuper)(&super, preprocessSEL(_cmd));
}

HTH

Приложение

Исходя из вашего комментария и поста кода в качестве другого ответа.

В своем коде вы пишете:

void* (*objc_msgSendSuperTyped)(id self, SEL _cmd) = (void*)objc_msgSendSuper;
return objc_msgSendSuperTyped((id) &super, preprocessSEL(_cmd));

Создание типичной копии указателя функции, а не просто приведение к использованию в качестве нашего предыдущего кода, это хорошо.Однако ваш код должен выдавать ошибку из XCode, когда вы пытаетесь присвоить типу без сохранения (&super - указатель структуры) на тип с сохранением (id) - что требует приведения с мостом.

Решение здесь состоит в том, чтобы дать objc_msgSendSuperTyped правильный тип, его первый аргумент должен быть указателем структуры:

void* (*objc_msgSendSuperTyped)(struct objc_super *self, SEL _cmd) = (void*)objc_msgSendSuper;
return objc_msgSendSuperTyped(&super, preprocessSEL(_cmd));

Из вашего комментария:

Мне пришлось изменить супер.super_class для super.class, чтобы он работал, теперь он выдает другие ошибки, не связанные.

Это говорит о том, что у вас есть некоторые необычные настройки, в объявлении objc_super мы находим:

#if !defined(__cplusplus)  &&  !__OBJC2__
   /* For compatibility with old objc-runtime.h header */
   __unsafe_unretained _Nonnull Class class;
#else
   __unsafe_unretained _Nonnull Class super_class;
#endif

__OBJC2__ определяется по умолчанию в Xcode 11 (и множестве более ранних версий) для файлов .m и .mm, __cplusplus определяется только для файлов .mm.Таким образом, условие !defined(__cplusplus) && !__OBJC2__ равно false, и поэтому поле называется super_class ...

Возможно, вы захотите определить, почему __OBJC2__ явно не определено для источника, который вы пытаетесь преобразовать...

0 голосов
/ 27 сентября 2019

Я нашел его работающим, изменив его на:

void* callSuper0(id self, Class superClass, SEL _cmd)
{
    struct objc_super super;
    super.receiver = (__bridge void *)self;
    super.class = superClass != NULL ? superClass : class_getSuperclass(object_getClass(self));

    void* (*objc_msgSendSuperTyped)(id self, SEL _cmd) = (void*)objc_msgSendSuper;
    return objc_msgSendSuperTyped((id) &super, preprocessSEL(_cmd));
}
...