http://pascal.net.ru/Somatic
Создал страничку, выражающую своё видение Somatic Pascal и Somatic Runtime.
http://pascal.net.ru/Somatic
Создал страничку, выражающую своё видение Somatic Pascal и Somatic Runtime.
Позавчера пришла по почте та самая книга «Handbook of Object Technology». На почтовой обёртке эпично красуется Value $0.07. Для своих семи центов книга в потрясающем состоянии. Страницы белые, свежие, не засаленные, ничего подобного. Следы пребывания в библиотеке есть, но это просто пустяки. Штампы RIT LIBRARY и WITHDRAWN на внешних сторонах страниц, следы оторванного кармана для карточки, приклеенный скотчем к обложке штрих–код, который я не рискну срывать. Худшее — это пометки карандашом на страницах, но это полная ерунда.
Поразила толщина. Теперь это самая толста книга по программированию, которая у меня есть. По толщине чуть уступает большому энциклопедическому словарю. Страницы в книге нумеруются не по порядку, а по главам, так что я, когда читал публично доступные главы, не догадывался о суммарном размере.
Впечатляет охват материалов. В этой книге есть 3 главы, посвящённые SOM (если в книге про объектные технологии не указан SOM, то такая книга — кошачий корм). Есть главы посвящённые языкам программирования, в том числе Ada 95, Modula-3, Smalltalk. CLOS, правда, нет, но SOM–то круче. An overview of the C++ Programming Language Страуструпа, кстати, впервые было опубликовано именно в этой книге, а уже потом распространялось отдельно. В PDF есть указание на книгу–первоисточник.
Весьма неплохо. И если о том, что я перечислил, я уже имел представление, то о многих других вещах в этой толстой книге у меня такого же хорошего представления нет. Вот, например, Business Object Notation. И таких глав 58.
Теперь хочу обзавестись «Putting metaclasses to work». Оба автора имели непосредственное отношение к разработке SOM 3.0, а сама книга оказала влияние, например, на Python. Что касается метаклассов, это самая упоминаемая книга. В электронном виде я её так и не нашёл, а б/у на таких же условиях, как Handbook of Object Technology, её нет. На http://www.alibris.com/ есть только новые, минимум за $250
Резюмирая полгода молчания про 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'ках только метаинформация со ссылками только на переопределённые методы.