Может ли methodSignatureForSelector: создать универсальную сигнатуру метода?

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

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


person Sridatta Thatipamala    schedule 30.03.2012    source источник


Ответы (2)


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

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

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

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

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

person bbum    schedule 30.03.2012

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

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

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

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

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

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

person newacct    schedule 11.05.2012