Как реализовать функцию IMP, которая возвращает большой тип структуры, определенный во время выполнения? - PullRequest
59 голосов
/ 29 марта 2011

Справочная информация: CamelBones регистрирует классы Perl во время выполнения Objective-C. Для этого каждый метод Perl зарегистрирован с одинаковым IMP функция; эта функция проверяет свои self & _cmd аргументы, чтобы найти какой метод Perl вызывать.

Это работало достаточно хорошо в течение нескольких лет, для сообщений, которые были отправлено с objc_msgSend. Но теперь я хочу добавить поддержку возвращение типов с плавающей точкой и больших структур из методов Perl. С плавающей точкой не сложно; Я просто напишу другой IMP, который возвращает double, для обработки сообщений, отправляемых с objc_msgSend_fpret.

Вопрос в том, что делать с objc_msgSend_stret. Написание разделять IMP для каждого возможного типа возвращаемого значения структуры нецелесообразно, поскольку две причины: во-первых, потому что даже если бы я сделал это только для структурных типов которые известны во время компиляции, это абсурдное количество функций. И во-вторых, поскольку мы говорим о фреймворке, который можно связать с любым произвольным кодом Objective-C и Perl, мы не знаем все потенциальные типы структур при компиляции фреймворка.

Я надеюсь написать один IMP, который может обработать любой возврат тип, который отправляется через objc_msgSend_stret. Могу ли я написать это как возвращая void и передавая указатель в буфер возврата, например старый objc_msgSend_stret был объявлен? Даже если это случилось с работать сейчас, могу ли я рассчитывать на то, что он продолжит работать в будущем?

Спасибо за любой совет - я ломал голову над этим. : -)

Обновление:

Вот совет, который я получил от одного из инженеров Apple, в их списке рассылки objc-language:

Вы должны написать ассемблерный код для обработки это дело.

В некоторых случаях ваше предложение не выполняется архитектуры, где ABI для "функции возвращая пустоту с указателем на структура как первый аргумент "отличается из "функции, возвращающей структуру". (На i386 структурный адрес выталкивается из стека вызывающей стороной в одном случай и вызываемый в другом случай.) Вот почему прототип для objc_msgSend_stret было изменено.

Код сборки будет записывать структурировать адрес возврата, переправить его в не-возвращаемый вызов функции C не мешая остальным параметры, а затем делать правильные ABI-специфическая очистка на выходе (ret $4 на i386). Как вариант, сборка код может захватить все параметры. Экспедиторская техника делает что-то подобное Этот код может быть в открытом исходном коде CoreFoundation если вы хотите увидеть, какие методы похож.

Я оставлю этот вопрос открытым, на тот случай, если кто-то придумывает более удачную идею, но с учетом того, что это исходит непосредственно от собственного "спорщика по времени выполнения" от Apple, я думаю, что это, вероятно, столь же авторитетный ответ, как я, вероятно, получу. Время отряхнуть справочные руководства по x86 и стереть ржавчину с моего ассемблера-фу, я думаю ...

1 Ответ

5 голосов
/ 23 мая 2011

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

  • Из кода среды выполнения Objective C: i386 и x86_64 заглушки сборок мессенджера, созданные вручную дляразличные методы обмена сообщениями.
  • SO-ответ , в котором содержится обзор диспетчеризации.
  • Углубленный обзор механизма диспетчеризации спострочный анализ кода сборки

Надеюсь, это поможет.

...