используя objc_msgSend для вызова функции Objective C с именованными аргументами

Я хочу добавить поддержку сценариев для проекта Objective-C с использованием среды выполнения objc. Теперь я сталкиваюсь с проблемой, что у меня нет подсказки, как я должен вызвать метод Objective-C, который принимает несколько именованных аргументов.

Так, например, следующий вызов цели-c

[object foo:bar]; 

может быть вызван из C:

 objc_msgSend(object, sel_getUid("foo:"), bar); 

Но как мне сделать что-то подобное для вызова метода:

 [object foo:var bar:var2 err:errVar]; 

??

Лучший Маркус

 objc_msgSend(object, sel_getUid("foo:bar:err:"), var, var2, errVar); 

Если одна из переменных является float , вам нужно использовать метод @Ken или обмануть реинтерпрет-литой:

 objc_msgSend(..., *(int*)&var, ...) 

Кроме того, если селектор возвращает float, вам может потребоваться использовать objc_msgSend_fpret , и если он вернет структуру, вы должны использовать objc_msgSend_stret . Если это вызов суперclassа, вам нужно использовать objc_msgSendSuper2 .

Принятый ответ близок, но он не будет работать должным образом для определенных типов. Например, если объявлен метод принятия float в качестве второго аргумента, это не сработает.

Чтобы правильно использовать objc_msgSend, вы должны отдать его соответствующему типу. Например, если ваш метод объявлен как

 - (void)foo:(id)foo bar:(float)bar err:(NSError **)err 

то вам нужно будет сделать что-то вроде этого:

 void (*objc_msgSendTyped)(id self, SEL _cmd, id foo, float bar, NSError**error) = (void*)objc_msgSend; objc_msgSendTyped(self, @selector(foo:bar:err:), foo, bar, error); 

Попробуйте описанный выше случай с помощью objc_msgSend и выйдите из полученных аргументов. Вы не увидите правильные значения в вызываемой функции. Эта необычная ситуация с литьем возникает из-за того, что objc_msgSend не предназначен для вызова как обычная C-функция. Он (и должен быть) реализован в сборке и просто перескакивает на целевую функцию C после запуска с несколькими регистрами. В частности, нет последовательного способа ссылаться на любой аргумент, предшествующий первым двум изнутри objc_msgSend.

Другой случай, когда просто вызов objc_msgSend прямо не будет работать, это метод, который возвращает NSRect, скажем, потому что objc_msgSend не используется в этом случае, objc_msgSend_stret is. В базовой функции C для метода, который возвращает NSRect, первый аргумент фактически является указателем на значение NSRect, а сама функция фактически возвращает void. Вы должны соответствовать этому соглашению при вызове, потому что это то, что предположительный метод будет считать. Кроме того, обстоятельства, в которых используется objc_msgSend_stret, различаются между архитектурами. Существует также objc_msgSend_fpret, который должен использоваться для методов, возвращающих определенные типы с плавающей запятой на определенные архитектуры.

Теперь, поскольку вы пытаетесь создать скриптовый мост, вы, вероятно, не можете явно использовать все случаи, с которыми работаете, вам нужно общее решение. В целом, это не совсем тривиально, и, к сожалению, ваш код должен быть специализированным для каждой архитектуры, на которую вы хотите настроить таргетинг (например, i386, x86_64, ppc). Лучше всего, чтобы увидеть, как это делает PyObjC . Вы также захотите взглянуть на libffi . Вероятно, неплохо понять немного больше о том, как параметры передаются в C, о которых вы можете прочитать в Руководстве по Mac OS X ABI . Наконец, Грег Паркер, который работает в среде выполнения objc, написал кучу очень хороших сообщений о внутренних функциях objc.

objc_msgSend (obj, @selector (foo: bar: err :), var, var2, & errVar);

  • Потяните, чтобы обновить UITableView без UITableViewController
  • Есть ли какие-либо frameworks для выделения текста в pdf-файле после рендеринга на iphone
  • Как resize UIModalPresentationFormSheet?
  • Как использовать NSTimer?
  • Лучший подход для синтаксического анализа XML на iPhone
  • Координаты текстуры OpenGL в пиксельном пространстве
  • Получение списка файлов в каталоге с глобусом
  • Воспроизведение музыки в фоновом режиме с помощью AVAudioplayer
  • Как использовать метод prepareForReuse
  • Как программно изменить оттенок UIImage?
  • Выполнение команды терминала из приложения Cocoa
  • Давайте будем гением компьютера.