Мохнатые уроды и моральные пёзды. Войти !bnw Сегодня Клубы

Резюмирая полгода молчания про SOM:
При портировании SOMObjects Toolkit на Borland C++ Free узнал заодно кучу интересных вещей о C как таковом (большинство примеров для него). Во–первых, есть такая очень весёлая проблема с разным манглингом в разных компиляторах. Символы в DLL можно импортировать двумя способами: через __declspec(dllexport) и __declspec(dllimport), а можно через .def файлы. Если через __declspec, то при экспорте компилятор сам выбирает имя, а это не всегда подходит. Разные компиляторы делают разный манглинг, и вообще, у SOM есть свои требования к именованию в таблице экспорта. Так что только .def. .def файл, похоже, под каждый компилятор нужно писать свой, потому что .def файл сопоставляет имя в таблице экспорта DLL с именем, как его манглит компилятор, когда читает заголовочный файл. Вот Borland, например, добавляет _ в начало cdecl функций и переменных, но никак не уродует stdcall функции, а GNU, я так понял, норовит добавить @размерстека. А VisualAge, под который было всё заточено, добавляет _ в начало и @размерстека в конец. Эта проблема худо–бедно решалась coff2omf, implib и тому подобными утилитами, которые все имена из одного уродства превращают в другое по одному алгоритму. Варьируя командную строку, обычно можно добиться результата. С SOM такое не прокатывает, потому что stdcall там перемешан с cdecl и переменными, и алгоритм должен быть для них разный. Запарился, в конечном итоге просто написал .def файлы руками, во всём SOM 3.0 около 1000 вызовов, не так уж много. Делая это, как не вспомнить импорт/экспорт в Delphi. function такая–то с соглашением таким–то, external оттуда–то с name таким–то. И не надо думать, какой манглинг получится в этом компиляторе для такого–то соглашения. Чётко и конкретно. Правда, нет импорта/экспорта переменных.
В somplatf.h по дефолту делается __declspec(dllexport) для Microsoft C. Как там происходит в MS, не знаю, но если в Borland я оставляю этот __declspec, то этот символ начинает торчать из DLL с тем манглингом, который мне не подходит наряду с нужным манглингом. Так что для Borland я дефайн поменял на пустой. Но если это так, то, может быть, и __declspec(dllimport) не нужен, ведь есть .lib, скомпилированный из .def? Ответ неверный. Для обычных функций генерится код вызова call туда–то, а для импортируемых функций — call dword ptr [там–то], плюс, генерятся трамплины, и, если подключить .lib, но в хедерах не использовать __declspec(dllimport), то компилятор создаёт неправильные вызовы, и всё крашится.
Ещё один источник радости — выбор рантайма в DLL. Так как программы на SOM в любом случае используют som.dll, то не будет лишним использовать и cc3250mt.dll. Всё компилится, даже что–то работает, но какие–то программы крашатся. Позже выясняется, что программы, выводящие на экран через somPrintf, работают, а через fprintf — нет. При отладке выясняется, что stdout не тот, который нужен. У cc3250mt.dll свой stdout, и только через него нужно делать fprintf, а, если не использовать /tWR, то stdout получается в .exe'шнике и не канает. Крашится, то есть. Реализация fprintf отнимает от адреса параметра FILE * адрес начала _streams и делит на sizeof(FILE). Если _streams в cc3250mt.dll, а stdout в .exe, получается дробное отрицательное число, и ничем хорошим это не кончается. По идее, у того, кто bcc32 сразу и компилит, и линкует, такого не происходит, но в нашем случае система сборки разделяет компилятор и компоновщик, поэтому может получаться такое рассогласование. В целом, с Borland вроде бы разобрался. Непроверенными остаются только нюансы с .dll, которые в примерах SOM используются только в DSOM, но DSOM службу я не поднимал. Я вижу, что всё компилится, я вижу, что импорты и экспорты без подчёркиваний, но для проверки надо поднять службу DSOM.
С .def файлами вообще весело. Я не знаю, это фишка Borland или в чём дело, мне .def для компиляции .dll и .def для создании библиотеки импорта (.lib) приходится генерить разные, хотя было бы логично, если в пределах одного компилятора как экспортировали, так и импортируем. То есть, в .def для .dll я пишу dAnimalClassData=_dAnimalClassData, а в .def для .lib — _dAnimalClassData=dAnimalClassData. Не знаю, можь это с переменными только такая петрушка.

Пока что завален рефератами. Из 6 рефератов в год удалось отвертеться от 4х и защитить 1. Надо защитить ещё один, плюс на работе проект важный. Летом, как освобожусь, надо продолжить. Есть желание сделать такой пакет Borland+SOM, чтобы студентоте в качестве Borland C++ подходил, работал без шаманства, в отличие от оф. версии. Оф. версия требует прописывания путей в bcc32.cfg и ilink32.cfg, плюс, не находит их, если путь к .exe'шнику bcc32 или ilink32 содержат в себе пробел. Всё это можно разрулить.
Ну а как бонус, там боеспособный SOM и демки к нему. Впечатляет, как мало весят .exe'шники и .dll'ки. Обычно, если используется ООП, всё быстро разбухает, несмотря на рантайм в отдельных .dll, а тут классы конструируются в рантайме, а в .exe'шниках и .dll'ках только метаинформация со ссылками только на переопределённые методы.

Рекомендовали: @j123123 @stiletto
#APUN84 / @octagram / 3976 дней назад

> Во–первых, есть такая очень весёлая проблема с разным манглингом в разных компиляторах. На эту тему советую http://agner.org/optimize/calling_conventions.pdf Там написано про манглинг
#APUN84/EFE / @j123123 / 3976 дней назад
@j123123 Да уж, я на такие таблицы насмотрелся уже. Только практика даёт окончательные ответы. Вообще, SOM должен скрывать от программиста такие подробности. SOM работает на уровне C, даже, если реализация на C++. По идее, на уровне C любой компилятор должно быть легко запинать, ведь это же C, не так ли? На Visual Basic у нас могут возникнуть трудности сделать DLL. В C++ as is будут проблемы с разными ABI исключений и классов. От C таких проблем интуитивно не ожидается, и тем не менее. Недостаточно прямой доступ к некоторым вещам.
#APUN84/WLM / @octagram --> #APUN84/EFE / 3975 дней назад
ipv6 ready BnW для ведрофона BnW на Реформале Викивач Котятки

Цоперайт © 2010-2016 @stiletto.