to post messages and comments.

← All posts tagged API

Думал, в Swift будут утилиты на Swift, а оказалось, что нет (см. #2891656). Ладно, посмотрим, какие есть ещё варианты. У нас же мостов для Java есть целых три штуки. А как там парсинг сделан?

Первым в голову приходит Rococoa. И там парсинг не сделан никак. Согласно документации, надо писать привязки вручную.

Про Apple Cocoa-Java известно мало, потому что он с закрытым кодом, но оттуда можно взять ручные коррекции, написанные прямо в Apple. Похоже, полновесного парсера типа GCC там нет. clang в те времена не было.

Порадовал GNUStep JIGS. Там есть и парсер, и ручные коррекции.

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

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

К слову о мобильных клиентах, а не сделать ли поддержку API, как в Twitter и identi.ca? Там не то StatusNet, не то ActivityStreams, что-то такое даёт взаимозаменяемость, и клиенты, поддерживающие одно, могут подключаться к другому, если нет жёсткой привязки.

Отдыхаю на API libnetfilter_conntrack:
1. Если где–то надо знать размер структур, то для них есть extern size_t nfexp_maxsize(void);
2. Если я захочу XML, я могу воспользоваться форматтером. А если не захочу, то мне не придётся парсить принудительно отформатированный XML, который я не просил. Я просто возьму данные из структур, которые мне придут в обработчик.
3. У обработчиков событий есть указатель на User_Data, как и положено в нормальных API.
4. И никаких varargs, ни даже va_list.

Ура! Откопал ещё такую штуку, как локальные процедуры в gcc, и работают они, как выясняется, так же, как и в GNAT, вот только локальную процедуру на Си из процедуры на Аде не вызовешь, а из локальной процедуры на Си надо тоже что–то вызывать, и удобно, чтобы это было тоже замыкание, только адское, и вот, замыкание замыканием погоняет, а внутри ещё varargs, но весь этот страх похоронен в деталях реализации, и снаружи всё красиво. Сделал, чтобы из этой штуки могло ещё и исключение вылететь, но только так, чтобы облетало стороной сишный код при помощи Save_Occurrence/Reraise_Occurrence.
Теперь осталось всего ничего, распарсить XML да загнать список многострадальных IP в контейнер–множество строк.

Поизучал API Dyncall. Заметно лучше, чем у libffi. Однако ту задачу, ради которой я обращаюсь к такой библиотеке в нативном языке, решить не может.
Здесь даются функции, при помощи которых можно забирать аргументы.
Вот только здесь нет возможности получить va_list, чтоб я его загнал в vasprintf. Не самому же мне реализовывать printf, как того требует libipset API.

Вот уже вторая библиотека с кривым API.
Чтобы создать сигнатуру функции, нужно указать разновидность ABI.
gcc -c -fdump-ada-spec -D__USE_GNU -C -fada-spec-parent=IPSet.Thin /usr/include/x86_64-linux-gnu/ffi.h
честно сгенерил:
subtype ffi_abi is unsigned;
FFI_FIRST_ABI : constant ffi_abi := 0;
FFI_SYSV : constant ffi_abi := 1;
FFI_UNIX64 : constant ffi_abi := 2;
FFI_LAST_ABI : constant ffi_abi := 3;
FFI_DEFAULT_ABI : constant ffi_abi := 2; — /usr/include/x86_64-linux-gnu/ffitarget.h:75
Однако, этот код получается специфичен для платформы x86_64-linux. Обычно нужен FFI_DEFAULT_ABI, но он везде разный. На x86-windows он будет равен FFI_MS_CDECL, который 5. Указать константное (в прямом смысле этого слова, а не как у libffi) значение типа 0 не получится. Разработчики позаботились, чтобы такие значения не корректировались к дефолту, а вызывали FFI_BAD_ABI. Функции, возвращающей значение по умолчанию, тоже не просматривается.
А, чтобы создать замыкание, нужно знать его размер, который тоже на разных платформах отличается, и нет функции, чтобы этот размер узнать. А знать это размер обязательно, ведь это аргумент ffi_closure_alloc, и если указать 0 или меньше, он мог бы тоже автоматически быть увеличен до минимального значения. Но нет. Размер идёт напрямую в malloc(), без коррекций. Впрочем, можно просто перебрать все папки для всех архитектур и узнать максимальный размер в 88 байтов (64 байта трамплина на CRIS CPU + 3 указателя) и выделять с запасом. Ну или добавить в адский проект сишный файлик чисто чтоб узнавать размер замыкания и значение по умолчанию, доделав за разработчиками их работу.

Нет, вы не подумайте, я вообще за open source всей душой, но опенсурщики сами напрашиваются, чтобы их код заслуженно считался парашей. Ну не было такого в WinAPI. Не было. Вообще, чем больше я вижу таких API, тем более божественным мне кажется WinAPI. Не помню, чтоб я там где–то так парился. Тот open source, за который я всей душой как–то сильно отличается от того open source, который есть.

Разбираюсь по работе с libipset API
Эти козлы сделали всё возможное, чтоб мне жизнь мёдом не казалось.
1. Чтобы мне получить список IP, присутствующих сейчас во множестве, мне нужно предоставить процедуру вывода, создать сессию, которая будет писать свой вывод этой процедурой, установить формат вывода XML, отправить команду list, подхватить вывод в буфер, распарсить XML из буфера, и только тогда я получу желанный список IP. Я вообще думал, для программистов должен быть какой–нибудь интерфейс попроще.
1. callback для вывода текста принимает varargs. Вот всю жизнь мечтал printf реализовать. Буду пробовать при помощи vasprintf оградить себя от этой пакости.
1. Нет UserData указателя, чтоб мне как–то отличать, кто пришёл в процедуру печати. Варианты лечения: создать пул трамплинов, использовать thread local storage или попробовать использовать GNAT'ский генератор трамплинов для замыканий. Последнее — сильная магия, но вдруг получится.

С WinAPI тааааааааакого геморроя не было. Не помню, чтоб там где–то мог быть CallBack без UserData. И varargs в stdcall не особо получится сделать всяким умникам.