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

61

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

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

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

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

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

Update:

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

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

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

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

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

  • 1
    Я не вижу причин, по которым вы не могли бы рассчитывать на void возврат и буферный способ ведения дел в будущем. objc_msgSend_stret не исчезнет в ближайшее время, и, пока вы выделяете достаточно памяти для буфера, я думаю, что у вас все будет хорошо. Но это, конечно, не самое элегантное решение.
  • 1
    Смотри выше. Кажется, простой способ не надежен. Ну да ладно, более или менее то, что я ожидал.
Показать ещё 5 комментариев
Теги:
objective-c-runtime

1 ответ

5

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

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

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

  • 0
    Спасибо, но как отправлять сообщения с помощью objc_msgSend * не тот вопрос, который я задал. У меня была эта часть хорошо в руке в течение многих лет. :-)
  • 0
    Извините, это моя ошибка. Я неправильно понял проблему. Я обновил свой ответ.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню