Может ли methodSignatureForSelector: создать сигнатуру «всеобъемлющего» метода? - PullRequest
2 голосов
/ 31 марта 2012

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

Я вижу, что подпись метода требует предоставления кодировок типов для каждого аргумента.Существует ли кодировка типа, которая означает абсолютно все (указатель, int, все остальное)?Иначе, есть ли другой способ добиться этого эффекта?

Ответы [ 2 ]

2 голосов
/ 11 мая 2012

Не могли бы вы подробнее рассказать об этом универсальном прокси-сервере и о том, что ему нужно переслать?

Если вашему прокси-серверу нужно только перенаправить каждое сообщение одной цели, он может сделать это в своем -forwardingTargetForSelector: во время выполнения. Если нет (например, вам нужно перенаправить на несколько целей или выполнить другие сложные манипуляции), вам нужно реализовать -forwardInvocation: для его обработки. Использование -forwardInvocation: для обработки вызовов требует, чтобы вы реализовали -messageSignatureForSelector:, потому что он должен получить сигнатуру метода, чтобы иметь возможность создавать вызов. (Даже если вы перенаправляете его на другой объект, этот объект также должен либо напрямую реализовать метод, добавить метод в ответ на +resolveInstanceMethod:, либо обработать его с помощью -forwardInvocation:, что требует, чтобы у него также была подпись. )

Подпись метода кодирует типы аргументов и тип возвращаемого значения. Причина, по которой эта информация необходима для вызова, заключается в том, что при передаче этих аргументов они размещаются во время компиляции (возможно, последовательно) в памяти в соответствии с их типами в объявлении. Большой параметр структуры будет занимать больше места, чем параметр int. Дабл также, вероятно, больше, чем int. Вызов должен хранить все эти аргументы и предоставлять вам доступ или изменять их по индексу. Невозможно выяснить, как аргументы располагаются во время выполнения, если вы не знали типы (или, по крайней мере, размеры типов).

Кроме того, механизм передачи сообщений отличается для методов, которые возвращают структуры (они вызывают objc_msgSend_stret), от других методов (они вызывают objc_msgSend) (а на некоторых платформах методы, возвращающие значение типа double, используют objc_msgSend_fpret). В первом случае структура не возвращается напрямую, но место для записи передается в качестве дополнительного аргумента-указателя в качестве параметра out. Поэтому знание типа возврата также важно для обработки вызова и возвращаемого значения в вызове.

Даже если вы пересылаете вызов другому объекту, в конечном итоге этот объект (или некоторый объект, который он пересылает вниз по строке) должен каким-то образом знать сигнатуру метода. Так почему бы не запросить этот объект для подписи селектора, когда он вам нужен?

Не существует "безопасной" подписи, которая будет работать для всех вещей, потому что разные типы имеют разные размеры.

2 голосов
/ 31 марта 2012

"вроде", но не совсем ... или, по крайней мере, не практически.

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

Во-первых, он действительно работает только для относительно простых типов аргументов.C ABI таков, что сложные аргументы - структуры, объекты C ++ и т. Д. - могут кодироваться в стеке хитроумными способами.Фактически, они могут быть закодированы таким образом, что для декодирования кадров недостаточно метаданных.

Во-вторых, любой тип системы, в которой «селекторы могут быть созданы пользователем произвольно», имеет очень отчетливый запах.об этом;запах "вы делаете это трудным путем".Objective-C, хотя он и был исключительно динамичным, на самом деле не был предназначен для поддержки этого уровня чистого шаблона мета-объекта.

Кроме того, любая такая получающаяся в результате система будет исключительно хрупкой.Что если «произвольный селектор» будет, скажем, @selector (hash)?

...