to post messages and comments.

← All posts tagged BridgeSupport

Думаю, что бы лучше взять для парсинга Objective-C API? То ли Рагель, то ли парсер комбинатор, то ли Виссером вдохновиться.

Решил подсмотреть, как сделано в Swift. А там — по-чёрному работа с clang идёт. Опыт BridgeSupport по переходу на clang был не самым удачным. С одной стороны, больше стало распознаваться, с другой стороны — стало фиг собрать. Moving target, понимаешь. А уж из-под винды это пытаться запустить я б не стал особенно сильно пытаться. Зря не пошли по пути аналогично COM TLB, SOMobjects IR, GObject IR и WinRT WinMD, в общем, как у всех остальных. BridgeSupport прямо-таки прокладывал дорогу в направлении здравомыслия. Но нет, теперь надо как-то по особенному подпрыгивать, чтоб всего лишь парсить API.

Всё же я погорячился насчёт BridgeSupport XML как аналога IDL/TLB/SOMIR для Objective-C. Например:

<function name='NSStringFromClass'>
<arg type='#'/>
<retval type='@'/>
</function>

Здесь видно, что на вход должен идти потомок NSClass, но это по историческим причинам. Видимо, не всегда в Objective-C поддерживались метаклассы, и ссылки на классы, как в Delphi, были разных типов со ссылками на объекты. Кроме NSClass, другие классы и протоколы чести попасть в кодирование типов не удостоились, а каким-то другим образом имена не пробрасываются. Вот, например, в данном примере потеряна информация о том, что результат — ссылка на NSString.Таким образом, это даже хуже, чем CORBA TypeCode, которые мне не нравились за то, что там терялась информация о пространстве имён класса и структуры.

Вот ещё пример метода NSString:

<method selector='getCString:maxLength:encoding:'>
<arg c_array_length_in_arg='1' index='0' type_modifier='o'/>
<retval type='B'/>
</method>

Я здесь вообще не могу понять, какого типа первый и второй аргумент. o значит out. А больше тут ничего и нету. А есть ещё третий, NSStringEncoding, между прочим.

Внимательно всмотрелся в кодирование типов на предмет char32_t, char16_t или wchar_t. Нету! А что же тогда будет возвращать NSString, если читать её по кусочкам? Пошёл смотреть сигнатуру метода в NSString.h:
— (unichar)characterAtIndex:(unsigned)index;А в Foundation.bridgesupport такого метода тупо нету. Интересный вопрос, почему. Если бы он как-то ставился в игнор, я бы его увидел в исключениях BridgeSupport\exceptions\Foundation.xml, но там тоже нету. Впрочем, учитывая, что
typedef unsigned short unichar;… я бы должен был увидеть S, формально не отличимый от unsigned short, и только эвристически, зная, что программисты становятся идиотами, экономящими два байта, только когда работают со строками, и что-то очень редко, работая с целыми числами и даже массивами из них, думают, ой нет, 4 байта-то многовато будет, надо два, понять, что S следует проецировать на Standard.Wide_Character в языке Ада и System.WideChar в языке Делфи, а не Interfaces.Unsigned_16 или Interfaces.C.unsigned_short в языке Ада и System.Word в языке Делфи.

Подводя итог, парсер для Objective-C придётся делать. Или делать clang -ast-dump или GCC-XML, если там Objective-C поддерживается, а BridgeSupport — вспомогательный инструмент.

Впрочем, довольно полезный с учётом того, что там промаркировали c_array_length_in_arg и модификаторы in, out, in out, имеющие синтаксическую поддержку в таких сравнительно более продвинутых нативных языках программирования, как Делфи и Ада. Первое в языке Делфи называется «открытыми массивами», а в языке Ада недоопределённые массивы — вообще органичная часть языка, ведь самые обычные строки там такие, и передача их как аргумент — это просто частный случай того, что можно сделать. Ну и когда сишную звёздочку не понятно, проецировать ли на in out, out или именно на указатель, это весьма раздражает. Если спроецируешь на in out или out, то нельзя без хаков передать null в языке Ада или nil в языке Делфи, а в некоторых API это можно и нужно, а в некоторых API — нельзя, и если язык мешает это сделать без хаков, то это к лучшему. Проекция на указатель более универсальна, но по сравнению с окружающим кодом, который нередко вообще без указателей, выглядит как что-то инопланетное.

Как же не люблю, когда всё пропадает из Интернета. Ну было же великое событие, появление BridgeSupport, до которого описание было только в заголовочных файлах Objective-C и не было аналога COM TLB, SOM.IR и т.п. Для Qt что-то такое уже было, для Gtk+ было, и только Cocoa была последней крепостью. И эта крепость пала. Всё это было в Mac OS X 10.5 Leopard, а у меня был Mac OS X 10.4 Tiger, но я следил за этими событиями, в частности, ставил MacPorts, и через него всё замечательно ставилось и на Тигре тоже. Недальновидные разработчики не могли придумать ничего лучше моста в Python и Ruby. Чуть более дальновидные на его основе сделали взамен устаревшего встроенного моста Cocoa-Java новый RoCocoa. И совсем то, что доктор прописал, было в первую очередь поступить с этой метаинформацией как в COM TLB, то есть, конечно же, привязки для Delphi и Ada, а уж потом всякие скрипты-шкрипты.