Много лет спустя пишу на Аде и обращаю внимание на то, что пишу практически в стиле единственного присваивания, благо адский declare-begin-end позволяет, и благо, начиная с Ada 2012 всё больше вещей можно записать выражениями. В этом плане Делфи уступает даже 83ей Аде. По принципу наименьших прав большинство значений между declare и begin — константы, и строки — соответственно, тоже. Кроме того, хотя есть Делфи-подобные строки (Unbounded_String в стандартной библиотеке и Universal_String в Матрёшке Вадима Годунко) со счётчиком ссылок, быстрее всего работают строки, размещаемые на стеке. Это которые самый обычный type String is array (Positive range <>) of Character, по принципу действия похожий на вариадические массивы в C99 и alloca(). После размещения на стеке у них размер поменять нельзя, а, значит, и нет особого смысла им не быть константой. И так получилось разделение на де факто немутируемые обычные строки и мутируемые строки в динамической памяти, похоже на String и StringBuilder .NET.
В каком-то смысле вернулся к тому, с чего начинал, с поправкой на то, что Unbounded_String как значение вполне себе пригоден для хранения в записях, массивах и контейнерах, в отличие от.
TDateTime(SysUtils.StrToFloat(…))Ан нет, E2089 Invalid typecast. Может, проблема в том, что результат StrToFloat — Extended, а не Double?
TDateTime(Double(SysUtils.StrToFloat(…)))Всё равно E2089 Invalid typecast. Да как же так? Сам ты инвалид!
Что самое удивительное, работает, если приведение типа НЕ ДЕЛАТЬ:
SysUtils.FormatDateTime(…, SysUtils.StrToFloat(…))Вот так компилируется и само приводится сквозь все Extended, Double и TDateTime, хотя я бы сильно не хотел, чтоб число с плавающей точкой случайно могло стать OLE датой/временем.
Ещё это сильно мешает привязки делать. По привычке возьмёшь напишешь type TPluginItem = type Pointer, и начинает тебе компилятор мозг выедать на ровном месте, а на неровном — соответственно, не выедать. Плюнешь, переделаешь в указатель на пустую запись с уникальным именем. Вот теперь получился указатель, который «не похож» на произвольно взятый другой указатель, но, к сожалению, всё ещё похож на указатель, чего лишний раз не хотелось бы, и от чего производный тип должен был спасти. Гипотетически для непохожести можно завернуть ещё дополнительно в запись, но тогда может сломаться работа с внешней библиотекой, ибо Delphi получает запись-результат всегда через дополнительный указатель, даже если она меньше размера двух указателей, как предписано stdcall. И тем более результат с плавающей точкой таким образом не приедет через регистр сопроцессора.
А вот на Аде берёшь и пишешь type OLE_Date_Time is new Long_Float или type Plugin_Item_Type is new Address, и работает это именно так, как ожидаешь. Одно в другое случайно не сконвертируется, а по требованию — всегда пожалуйста, без этих дурацких непонятных ошибок. И, конечно, на Аде, когда пишешь пакет, можно просто написать в публичной части type Plugin_Item_Type is private, и всё, внутреннее устройство для внешнего мира становится непрозрачно. Если нужно, функции конвертации из/в Address можно написать в дочернем пакете, чтоб глаза не мозолило в родительском. А то в Delphi, C и C++ вечно свалка в пространстве имён, хочется закрыться руками от падающих отовсюду в пространство имён гор мусора.
скачать её с сайта Indy. А вот и нет! Где библиотека, где патч, интересные люди, однако.
Полазив по форумам, нашёл такую ссылку. Скачал самую свежую. Не подошло. Методично качал другие версии с конца, потом методом дихотомии, потом тупо взял самую старую версию. Смотрел в ФАРе, есть там эти долбаные нестандартные функции или нет. Нету. Нигде. Заглянул в архив и там прямо явно видно версии с Indy в названии. Наверное, оно. Скачал 0.9.8l. Не подошло. Скачал 0.9.8h. Не подошло. Действительно, если смотреть, что там внутри, то префиксы _indy видать, но это не всё, что нужно. Оказывается, IdSSLOpenSSLHeaders10.pas там не для красоты, и без него не работает. Я ведь хотел, чтоб Indy не пересобирать, думал, на интерфейс к новым функциям можно забить, а оказывается, что там и основной интерфейс переделан, поэтому каких-то нестандартных функций нет. Впрочем, пересобирать весь Indy не пришлось, достаточно было положить только этот файлик под правильным именем в директорию проекта, он заменил собой предустановленный dcu и нормально скомпоновался с остальными модулями.
Потом выяснилось, что хотя в Delphi 2007 версия Indy 10, но если бы я на сайте Indy зашёл в Indy 9, то там была бы ссылка на SSL Support DLL's, а оттуда — на Fulgan. Если б знал, что там всё настолько плохо, попробовал начать с WinInet. Авось его неумение в SNI проканает.
Решил не так давно делать веб-запросы в программе на необновлённом Indy. Кто его знает, этого заказчика, сможет он свежую поставить или нет. Узнал много нового. Оказывается, обычная библиотека OpenSSL к Indy не подходит, потому что там требуются некоторые функции специально для Indy вроде SSL_CTX_set_options_indy. Думаю, раз она в комплект не входит, надо Полазив по форумам, нашёл такую ссылку. Скачал самую свежую. Не подошло. Методично качал другие версии с конца, потом методом дихотомии, потом тупо взял самую старую версию. Смотрел в ФАРе, есть там эти долбаные нестандартные функции или нет. Нету. Нигде. Заглянул в архив и там прямо явно видно версии с Indy в названии. Наверное, оно. Скачал 0.9.8l. Не подошло. Скачал 0.9.8h. Не подошло. Действительно, если смотреть, что там внутри, то префиксы _indy видать, но это не всё, что нужно. Оказывается, IdSSLOpenSSLHeaders10.pas там не для красоты, и без него не работает. Я ведь хотел, чтоб Indy не пересобирать, думал, на интерфейс к новым функциям можно забить, а оказывается, что там и основной интерфейс переделан, поэтому каких-то нестандартных функций нет. Впрочем, пересобирать весь Indy не пришлось, достаточно было положить только этот файлик под правильным именем в директорию проекта, он заменил собой предустановленный dcu и нормально скомпоновался с остальными модулями.
Потом выяснилось, что хотя в Delphi 2007 версия Indy 10, но если бы я на сайте Indy зашёл в Indy 9, то там была бы ссылка на SSL Support DLL's, а оттуда — на Fulgan. Если б знал, что там всё настолько плохо, попробовал начать с WinInet. Авось его неумение в SNI проканает.
А вот на Линуксе я же помню, что вылезает, если с ЦентОСа на Дебиан перенести бинарник. Сразу то символ в glibc не той версии, то сегфолт, то ещё что-нибудь не заладится. Интересно, как с этим новый Делфи справляется. Ведь ему же не дают полапать конфигурацию операционной системы разработчика, и он не может к ней глубоко привязаться, как это любит делать всё автотулзовое и вообще чуть ли не всё линуксовое.
Собственно, пока я окончательный бинарник так и не смог получить, а только .o. То есть, так же просто, как с Мак ОСом, уже не работает. Если пытаться что-то сделать из IDE, хотя бы Build или Compile, без Run, при любом раскладе IDE требует подключить к paserver на Linux, а если нет, то и компилировать не будет. Попытался задействовать в качестве платформы paserver «Bash на Ubuntu», то есть, WSL, и не смог скопировать paserver туда. Помедитировал на вывод mount и ls / в этом bash, не нашёл ничего похожего на файловую систему Windows. Это действительно параллельная Вселенная. Можно, конечно, на сайт залить, а потом wget'ом скачать, но решил дождаться установки Creators Update, а пока пойти другим путём.
MarshaledAString вместо PAnsiChar. Открыл System.pas, нашёл там при включенном NEXTGEN такое:
Также огорчило, что до сих пор нет нормальных 32битных символов и строк. В языке Ада они уже 12 лет как появились как неотъемлемая часть стандарта. Как можно идти на Линукс без 32битных строк? В API открытых библиотек Юникод, сколько я видел, любой libidn возьми, всегда представлен 32битными строками. Открыл System.pas, увидел там type UCS4Char = type Cardinal для всех платформ, где Cardinal — это беззнаковое 32-битное целое, а type … = type … в Делфи делает новый тип, не совместимый со старым без приведения типа, аналог адского type … is new …
Ещё посмотрев по сторонам, нашёл StdDefTypes.inc , а в нём — type wchar_t = Int32
Ни методов TMarshal, ни попыток аналогично скрыть указатель вроде Marshaled32String, ничего такого. Высокопоставленные китайские чиновники с именами из иероглифов за пределами BMP, а также все причастные, которым текст с этими именами надо обрабатывать, не одобряют это.
Почитал сорцы в linuxrtl, бросилось в глаза _PAnsiChr = _PAnsiChar;При этом _PAnsiChar не объявляется, то есть, он встроенный. Без NEXTGEN _PAnsiChr = привычному PAnsiChar. Напрашивается мнение, что из MarshaledAString пытаются лепить типа-не-указатель, который надо класть в System.TMarshal. Судя по тому, что WriteLn(X) и X[0] := '2' компилируются, природа этого типа пока ещё не совсем замаскирована.
MarshaledAString = _PAnsiChr;
Также огорчило, что до сих пор нет нормальных 32битных символов и строк. В языке Ада они уже 12 лет как появились как неотъемлемая часть стандарта. Как можно идти на Линукс без 32битных строк? В API открытых библиотек Юникод, сколько я видел, любой libidn возьми, всегда представлен 32битными строками. Открыл System.pas, увидел там type UCS4Char = type Cardinal для всех платформ, где Cardinal — это беззнаковое 32-битное целое, а type … = type … в Делфи делает новый тип, не совместимый со старым без приведения типа, аналог адского type … is new …
Ещё посмотрев по сторонам, нашёл StdDefTypes.inc , а в нём — type wchar_t = Int32
Ни методов TMarshal, ни попыток аналогично скрыть указатель вроде Marshaled32String, ничего такого. Высокопоставленные китайские чиновники с именами из иероглифов за пределами BMP, а также все причастные, которым текст с этими именами надо обрабатывать, не одобряют это.
Delphi для Linux. Компилятор командной строки называется dcclinux64.exe. И там ARC для ссылок на объекты, что было бы очень круто, если не отсутствие поддержки ARC в компиляторах для Windows и Mac OS X. Ну покажите мне такого человека, которой будет писать из-под Винды (и не из-под чего другого) на Линукс (и не подо что другое). Потому что если в целевых платформах затёсывается хоть одна не-ARC, это во всём общем коде становится нельзя положиться на его наличие, всюду вылезают лестницы try-finally, то есть, ARC, считай, что и нет, наоборот, только геморроя добавляется предусматривать постоянно оба случая.
Это напоминает поведение хозяина, который, чтобы собаке было не так больно, режет ей хвост по частям. Linux уже там, а Windows и Mac OS X — ещё здесь. Ожидается, что и Windows будет там, но ещё нет, и пока крутитесь, как хотите.
Для Delphi обычно параллельно выпускается комплементарный C++ Builder, зеркалирующий в C++ особенности Delphi вроде свойств объектов, неявных метаклассов или пресловутого ARC, и синхронизирующий ABI вплоть до наследования классов между языками. Но для Linux я никакого такого компилятора не увидел. Нет bcclinux64.exe, и из IDE, если создать новый консольный проект, нельзя выбрать целевую платформу Linux. Немного неожиданно, ведь кроме одного все компиляторы C++ Builder основаны на clang и LLVM, в том числе для Android, который почти Linux.
Забавно, что для Win32, наоборот, есть сразу два компилятора, bcc32.exe без ARC и bcc32c.exe с ARC. Там тоже режут хвост по кусочкам, но начинают с другого конца. Ох, копец.
Если вдруг ограничиться только Линуксом, только Делфи (без комплементарного Делфям C++, но всё остальное, конечно, можно, включая Аду GNAT и комплементарный Аде G++), и только из-под Виндоуз, тогда всё супер. Хоть в чём-то Делфи становится лучше Ады. А так — копец.
Посмотрел немного на Это напоминает поведение хозяина, который, чтобы собаке было не так больно, режет ей хвост по частям. Linux уже там, а Windows и Mac OS X — ещё здесь. Ожидается, что и Windows будет там, но ещё нет, и пока крутитесь, как хотите.
Для Delphi обычно параллельно выпускается комплементарный C++ Builder, зеркалирующий в C++ особенности Delphi вроде свойств объектов, неявных метаклассов или пресловутого ARC, и синхронизирующий ABI вплоть до наследования классов между языками. Но для Linux я никакого такого компилятора не увидел. Нет bcclinux64.exe, и из IDE, если создать новый консольный проект, нельзя выбрать целевую платформу Linux. Немного неожиданно, ведь кроме одного все компиляторы C++ Builder основаны на clang и LLVM, в том числе для Android, который почти Linux.
Забавно, что для Win32, наоборот, есть сразу два компилятора, bcc32.exe без ARC и bcc32c.exe с ARC. Там тоже режут хвост по кусочкам, но начинают с другого конца. Ох, копец.
Если вдруг ограничиться только Линуксом, только Делфи (без комплементарного Делфям C++, но всё остальное, конечно, можно, включая Аду GNAT и комплементарный Аде G++), и только из-под Виндоуз, тогда всё супер. Хоть в чём-то Делфи становится лучше Ады. А так — копец.
TestValue := TCalDayOfWeek(20);Такой оператор молча проглотил ошибку, что меня как адиста, конечно, возмущает.
TestValue := dowMonday + 20;Такой оператор не компилируется, но направление мысли было верным. Ещё немного подумав, я нашёл ближайший аналог на Делфи:
TestValue := dowMonday;В этом случае бросается ERangeCheckError, что и требовалось.
Inc(TestValue, 20);
На Аде я бы написал TCalDayOfWeek'Val (выражение) без необходимости во временной переменной.
Но в языке Ада, наоборот, нет такого всеядного Inc, как в Делфи. Как адаисту, мне кажется, что это чаще разумно, чем нет. Если перечисляемый тип гоняется в число и обратно, пусть это всё в явном виде будет написано. А вдруг написан бред? Когда всё потенциально бредовое требуется в явном виде расписать, заметить бредовость легче.
ARC forbids Objective-C objects in structs or unionsА Objective-C, оказывается, не так крут, как я думал. Хотя, казалось бы, какие проблемы. Везде в других местах (и в C++ тоже) такое работает.
System.Generics.Collections.TDictionary в Делфи перебираем пары ключ-значение, а при переборе стандартного Ada.Containers.Hashed_Maps — только сами значения.
В обоих языках появились конструкции для удобного перебора коллекций. for-in-do в Делфи и for-of-loop в языке Ада. Но в языке Ада можно и нужно возвращать ссылочный тип, и под такой перебор не нужно объявлять переменную, а в Делфи — нужно, и нужно именно затем, что оно всё будет при переборе постоянно копироваться и уничтожаться, хоть там какой развесистый record внутри. Но зато при переборе стандартного По этому поводу получил возможность забуриться в свежий Делфи Токио. И сравнить с Адой. Первым делом зашёл в настройки проекта посмотреть, как там дела по умолчанию со включениям проверок времени выполнения. Негусто. Всё выключено. Никак видеокодеки опять пишем или на Розеттакоде секундами меряемся. Часы моего времени на отладку дороже, поэтому всё врубил. Во всяком случае, всё, что смог, а было там только три галочки. Но совсем как в Аде писать всё равно не получилось. Не хватило ещё проверки указателя на null-nil до того, как пытаться по нему пройти. На Аде я могу забуриться внутрь сложного JSON значения, а если где-то что-то не нашлось, вылететь по известному исключению в обработчик, который ничего не сделает. В Делфи, по крайней мере, в стандартной библиотеке, если не брать мои CVariants, такая история не работает. Ну или лучше не пользоваться. «X.Values['ObjectKey'] as TJSONString» запросто может оказаться nil, и если дальше у него получить Value, то вылетает исключение Access Violation с доступом к первым байтам виртуальной памяти. Чё-т как-то не очень такое ловить. Лучше б что-то языковое бросалось ДО попытки вызвать метод через такой указатель.
Освежил воспоминания, почему @akastargazer так радовался, что в Обероне не надо так париться управлением памятью. Как адаисту со стажем, мне это было не очень понятно, что там париться, и зачем решать эти проблемы таким изуверским способом, а тут вот оно всплыло. За каждый TJSONObject и TJSONPair трясёшься, чтоб он только не утёк, если на полпути исключение вылетит. Всё огораживаешь в try-finally-FreeAndNil-end, всем значениям, которые могли бы при прочих равных быть промежуточными, даёшь имя переменной. В GNATCOLL.JSON такого страха не было, и в моих делфёвых CVariants такого страха нет. Там RAII и счётчик ссылок внутри. Но столбовой дорогой это до сих пор не стало.
UniGUI Web App Development
Присмотрел на сайте Embarcadero семинар, который мне удобен по времени. Заранее поставил отметку «Пойду».
На почте пусто, по ссылке пусто. У FMSoft или uniGUI каких-то Твиттеров не наблюдается как резервного средства оповещения. В официальных фейсбуке и твиттере Делфи про вебинар нет. Копец.
Присмотрел на сайте Embarcadero семинар, который мне удобен по времени. Заранее поставил отметку «Пойду».
Start Date: Jun 22 2017 at 19:00То есть, по универсальному времени это час ночи 23 июня, а по барнаульскому — 8 утра 23 июня. То есть, сейчас уже 10 минут как идёт. А куда заходить-то, алё?
На почте пусто, по ссылке пусто. У FMSoft или uniGUI каких-то Твиттеров не наблюдается как резервного средства оповещения. В официальных фейсбуке и твиттере Делфи про вебинар нет. Копец.
Общая платформа исполнения приложений как последний шанс для Delphi и Ada
В обстановке, когда всякие разработчики нет-нет, да и «забудут» то про Delphi, то про Аду, Платформа — это соломинка, за которую делфистам и адаистам нужно ухватиться и держаться. Платформа предполагает целый комплекс мер по мотивации разработчиков использовать именно её, а не что-то другое. Тут и импортозамещение, и экспорт в сценарные языки программирования, более лёгкий, чем в SWIG, и многое другое, и попутно такие компоненты становятся доступны в Delphi и Ada с относительно удобным программным интерфейсом.
Delphi для Linux стоит минимум $2400. Могу себе представить откаты. Ну теперь-то импортозамещение пойдёт в гору.
Windows 10: From WinRT to Centennial with Marco Cantu; длительность 54 минуты
Ну вот, наконец, доклад по WinRT не от Microsoft, у которых, конечно, в их параллельной Вселенной всё без проблем, а как на самом деле, без мнения третьей стороны не понятно. Мне вообще наиболее интересна была бы связка Centennial+Islandwood, чтоб в вендор локе WinRT так уж сильно не увязнуть, но это с кондачка не поднять.
И да, то обновление, которое должно было быть в ноябре, не принесло поддержку Linux ARC, но поддержка Project Centennial там имеется, об этом и доклад. И это именно то, что сейчас можно скачать на шару.
Ну вот, наконец, доклад по WinRT не от Microsoft, у которых, конечно, в их параллельной Вселенной всё без проблем, а как на самом деле, без мнения третьей стороны не понятно. Мне вообще наиболее интересна была бы связка Centennial+Islandwood, чтоб в вендор локе WinRT так уж сильно не увязнуть, но это с кондачка не поднять.
И да, то обновление, которое должно было быть в ноябре, не принесло поддержку Linux ARC, но поддержка Project Centennial там имеется, об этом и доклад. И это именно то, что сейчас можно скачать на шару.
Интеграция внешней объектной системы в Delphi на примере IBM SOM
Один из моих проектов реализует поддержку SOM в Delphi. Разработка начиналась на Delphi, пришлось часть привязок делать вручную и не так красиво, в процедурном стиле, без проверки типов. Используя эти привязки, был написан генератор привязок в объектном стиле, а затем и сам генератор был переписан на новые привязки, став подтверждением их работоспособности. Ради красоты пришлось хакнуть объектную систему Delphi, и, может быть, вам будет интересно, как это вообще можно делать.
Это пример для старых привязок, а это — для новых. В старых привязках SOMObject — это указатель на запись, а все остальные классы — синонимы SOMObject, то есть, контроля типов нет. В старых привязках, чтобы узнать тип аргумента, нужно было в процедурном стиле написать ParameterDef__get_type, а вот имя аргумента объявлялось в Contained, поэтому Contained__get_name, а так как вручную мне лень синонимы везде прописывать, то только по таким именам работало. В новых привязках генератор собирает все методы класса в одну общую кучу, и всё работает достаточно очевидным образом с вызовом методов через точку. И даже атрибуты CORBA спроецировались на свойства Delphi. Поскольку в Delphi жалкое одиночное наследование, генерить список методов требуется каждый раз сначала, и именно это и делается, зато потом удобно.
Работает это посредством того хака, что создаются объекты SOM, а Delphi думает, что это объекты Delphi. Так как с точки зрения Delphi методы статические, Delphi не лезет в VMT, делает статический вызов, в нём написан код, который направит вызов в SOM, и оно там пойдёт куда надо. Ещё немного пошаманил, чтобы волшебным образом работали классовые функции. Классовые функции могут вызываться как у объектов, и тогда Delphi пытается взять из объекта VMT по нулевому смещению, а может — непосредственно у класса, и тогда берётся статический адрес VMT. Учитывая, что с точки зрения Delphi классы друг от друга не наследуются, отличить эти случаи не сложно. Нужно просто сравнить Self со своим именем, и если да, то нас вызвали через имя класса, и класс-объект нужно искать одним способом, а если нет, то нас вызвали как метод объекта, и надо ещё раз разъименовать Self, и там будет лежать указатель на класс-объект.
Немного подкрутил, чтобы в результате метода SOMObject.somGetClass учитывался метакласс. Была мысль вообще все методы метакласса спроецировать на классовые функции и процедуры, но потом посмотрел, сколько там всего в SOMClass, и решил, что не надо. Тем более, что в SOM.IR публично показан только один метакласс, SOMMSingleInstance. Но даже ради него подкрутил, чтобы у метода SOMObject.somGetClass возвращался именно указанный метакласс, а не просто SOMClass. Кстати, так получается, что с точки зрения языковой проекции метаклассы не могут так просто наследоваться. То есть, умом-то мы понимаем, что компилятор SOM гарантирует совместимость метаклассов, но вот во что это спроецировать, открытый вопрос. Если мы наследуемся от двух классов с разными метаклассами, то метакласс потомка будет заведомо принадлежать пересечению множеств потомков каждого метакласса, и что, для этого динамически создаваемого метакласса тоже создавать привязки? А там по цепочке ещё для метаклассов более высокого порядка может потребоваться автоматическое создание. Одно дело — когда движок SOM это создаёт, и другое дело — когда генерится текст. Я решил, что этого делать не нужно, а раз так, то даже, если был класс A с указанием метакласса M_A, и от него наследуется класс B, то, если B не укажет явно тот же метакласс, что и A, в его привязках будет опять обычный SOMClass.
Естественно, все методы обычного TObject не будут работать. Я эту проблему пытаюсь решить, скрывая их при помощи reintroduce в private. Только операция as портит картину. Её не спрячешь, но хотя бы заменил методами, приводящими тип вверх и вниз. Вот так, с небольшой порцией магии создаётся впечатление, что SOM в Delphi как родная. Классы, методы, свойства.
Раздраконил свой генератор привязок до такого состояния, что уже заработала программа, использующая исключительно новые привязки. Работает это посредством того хака, что создаются объекты SOM, а Delphi думает, что это объекты Delphi. Так как с точки зрения Delphi методы статические, Delphi не лезет в VMT, делает статический вызов, в нём написан код, который направит вызов в SOM, и оно там пойдёт куда надо. Ещё немного пошаманил, чтобы волшебным образом работали классовые функции. Классовые функции могут вызываться как у объектов, и тогда Delphi пытается взять из объекта VMT по нулевому смещению, а может — непосредственно у класса, и тогда берётся статический адрес VMT. Учитывая, что с точки зрения Delphi классы друг от друга не наследуются, отличить эти случаи не сложно. Нужно просто сравнить Self со своим именем, и если да, то нас вызвали через имя класса, и класс-объект нужно искать одним способом, а если нет, то нас вызвали как метод объекта, и надо ещё раз разъименовать Self, и там будет лежать указатель на класс-объект.
Немного подкрутил, чтобы в результате метода SOMObject.somGetClass учитывался метакласс. Была мысль вообще все методы метакласса спроецировать на классовые функции и процедуры, но потом посмотрел, сколько там всего в SOMClass, и решил, что не надо. Тем более, что в SOM.IR публично показан только один метакласс, SOMMSingleInstance. Но даже ради него подкрутил, чтобы у метода SOMObject.somGetClass возвращался именно указанный метакласс, а не просто SOMClass. Кстати, так получается, что с точки зрения языковой проекции метаклассы не могут так просто наследоваться. То есть, умом-то мы понимаем, что компилятор SOM гарантирует совместимость метаклассов, но вот во что это спроецировать, открытый вопрос. Если мы наследуемся от двух классов с разными метаклассами, то метакласс потомка будет заведомо принадлежать пересечению множеств потомков каждого метакласса, и что, для этого динамически создаваемого метакласса тоже создавать привязки? А там по цепочке ещё для метаклассов более высокого порядка может потребоваться автоматическое создание. Одно дело — когда движок SOM это создаёт, и другое дело — когда генерится текст. Я решил, что этого делать не нужно, а раз так, то даже, если был класс A с указанием метакласса M_A, и от него наследуется класс B, то, если B не укажет явно тот же метакласс, что и A, в его привязках будет опять обычный SOMClass.
Естественно, все методы обычного TObject не будут работать. Я эту проблему пытаюсь решить, скрывая их при помощи reintroduce в private. Только операция as портит картину. Её не спрячешь, но хотя бы заменил методами, приводящими тип вверх и вниз. Вот так, с небольшой порцией магии создаётся впечатление, что SOM в Delphi как родная. Классы, методы, свойства.
#2807187 я выяснил, что в Delphi самое сложное — это неразрывный блок type. Все отложенные определения типов к концу блока должны случиться. Поэтому (с точки зрения, где сложнее и рискованнее) поддержка SOM начинается с Delphi, а в самом проекте SOM-Delphi — с блока type. Вот, чего удалось добиться: SOMIRTest.DumpOut.pas. Компилятору Delphi сейчас не хватает только реализации методов, но это уже совсем другое дело. Это не блок type. Пока я тут прыгал с EF на IRF, у меня тут достаточно текстовых заготовок осталось, чтоб написать методы.
Что удалось выяснить: в доках было чётко написано:
Среди расширений CORBA TypeCode kind: внешние типы (tk_foreign), указатели (tk_pointer), циклические ссылки (rk_self). Удалось сделать такую эвристику, чтобы внешние типы по максимуму были определены не сами по себе, а только через указатель. Вот, например, Emitter Framework любит поработать с FILE* из VisualAge C++ RTL. Нашлись методы, которые «указательность» воплощают не через tk_pointer, а через режим аргумента in out, и заставляют алгоритм-таки объявить внешний тип явно. Там тоже немного подкрутил, в Delphi как раз есть синтаксис аргументов "var X" и "out Y" без указания типа. Из четырёх осталось два автоматом объявленных как явные указатели (somId и va_list), и так оно и есть в их случае.
Нашлись и недостатки по сравнению с EF. В EF есть комментарии, а в IRF — нет. Без комментариев уже доки не погенерить, например. Martin Iturbide, владельцу edm2.com, пригодилось бы, он у себя на wiki размещает. Ещё в EF все типы конкретно определены, а в IRF всё делается через CORBA TypeCode. Все пользовательские типы видны как объекты TypeDef, но потом, когда эти типы используются, в CORBA TypeCode видно только конечный результат с учётом всех подстановок. Сохраняются имена только у сложных типов, таких, как записи, перечисляемые и внешние типы, но они содержат не полный идентификатор, то есть, от корня, а просто имя, и его приходится эвристически разрешать, если хотим, чтобы всё было красиво, и эта эвристика, вообще говоря, заведомо менее надёжна. Таким образом, будет не лишне иметь эмиттер, работающий аналогично IR emitter, собирающий всё в одном месте, но просто побольше информации.
В Что удалось выяснить: в доках было чётко написано:
For this reason, the use of the -u compiler flag requires that all of the types mentioned in the IDL source file must be fully defined within the scope of the compilation. Warning messages from the SOM Compiler about undefined types result in actual error messages when using the -u flag.То есть, как раз то, что мне не оказалось неприемлемым в EF в купе с невозможностью обработать информацию из нескольких IDL за один проход. Однако, каким-то образом ссылки на отсутствующие классы всё же попали в SOM.IR, на той строке, куда я решёткой поставил ссылку.
Среди расширений CORBA TypeCode kind: внешние типы (tk_foreign), указатели (tk_pointer), циклические ссылки (rk_self). Удалось сделать такую эвристику, чтобы внешние типы по максимуму были определены не сами по себе, а только через указатель. Вот, например, Emitter Framework любит поработать с FILE* из VisualAge C++ RTL. Нашлись методы, которые «указательность» воплощают не через tk_pointer, а через режим аргумента in out, и заставляют алгоритм-таки объявить внешний тип явно. Там тоже немного подкрутил, в Delphi как раз есть синтаксис аргументов "var X" и "out Y" без указания типа. Из четырёх осталось два автоматом объявленных как явные указатели (somId и va_list), и так оно и есть в их случае.
Нашлись и недостатки по сравнению с EF. В EF есть комментарии, а в IRF — нет. Без комментариев уже доки не погенерить, например. Martin Iturbide, владельцу edm2.com, пригодилось бы, он у себя на wiki размещает. Ещё в EF все типы конкретно определены, а в IRF всё делается через CORBA TypeCode. Все пользовательские типы видны как объекты TypeDef, но потом, когда эти типы используются, в CORBA TypeCode видно только конечный результат с учётом всех подстановок. Сохраняются имена только у сложных типов, таких, как записи, перечисляемые и внешние типы, но они содержат не полный идентификатор, то есть, от корня, а просто имя, и его приходится эвристически разрешать, если хотим, чтобы всё было красиво, и эта эвристика, вообще говоря, заведомо менее надёжна. Таким образом, будет не лишне иметь эмиттер, работающий аналогично IR emitter, собирающий всё в одном месте, но просто побольше информации.
Вообще, IBM, наверное, на все, какие только можно, грабли наступили в своём ABI:
Импорт/экспорт структур данных между DLL
cdecl varargs
Смешение cdecl и stdcall в одной библиотеке импорта для C
enum, которые внезапно оказались байтового размера
Теперь ещё структуры в результатах
SOMIRTest.DumpOut.pas
Ну вот, уже как-то повеселее пошло. Зря не начал сразу с SOM IR. Я тут подсчитал, с учётом крюка через Emitter Framework я вручную написал привязки для почти половины классов (37/75). Классы Emitter Framework чем-то похожи на Interface Repository. И там, и там есть модули (пространства имён), интерфейсы (классы), операции (методы), typedef, но в Interface Repository типы кодируются CORBA TypeCode с нехитрым сишным API, а в Emitter Framework под каждый struct, enum и sequence — отдельный класс. Пока нет генератора, привязывать классы получается дольше.
Ну вот, уже как-то повеселее пошло. Зря не начал сразу с SOM IR. Я тут подсчитал, с учётом крюка через Emitter Framework я вручную написал привязки для почти половины классов (37/75). Классы Emitter Framework чем-то похожи на Interface Repository. И там, и там есть модули (пространства имён), интерфейсы (классы), операции (методы), typedef, но в Interface Repository типы кодируются CORBA TypeCode с нехитрым сишным API, а в Emitter Framework под каждый struct, enum и sequence — отдельный класс. Пока нет генератора, привязывать классы получается дольше.
…а также функций для конвертации между WideString и UCS4String, а в юникодных Delphi — также между UnicodeString и UCS4String. Поскольку UCS4Char — это не символ, а замаскированное число, в теле программы такие литералы так просто не попишешь. Хотя, конечно, можно приводить тип постоянно. UCS4String — это вообще не строка, а динамический массив, и плюс на нём не сработает. Также для массивов не работает COW. Для строк Delphi автоматически добавляет в конец нулевые байты в нужном количестве на случай, если эту строку захотят послать в ущербные сишные API, вот она как раз бы и подошла сразу, а для динамического массива беззнаковых чисел такого делаться не будет, поэтому это делают функции конвертации. Соответственно, Length вернёт либо 0 для пустой строки, либо длину, на 1 большую настоящей длины. Так что даже если вдруг для динамических массивов заработает плюс, он будет косячить. В array of const и Variant, я так понимаю, UCS4String тоже просто так не влезет.
Но больше всего у меня горит от того, что в неюникодных Delphi функции конвертации поддерживают только BMP. Семёрка, похоже, если и сдохнет, то только со всеми Delphi вообще. Embarcadero так и не приложили усилий, чтобы это могло быть иначе.
форуме новую шапку. Для БлэкБокса чёт не смог найти вменяемого качества картинку
Забубенил себе на
im_kos форкнул репозиторий OCTAGRAM/delphi-yaml под именем im_kos/delphi-yaml
im_kos форкнул репозиторий OCTAGRAM/delphi-cvariants под именем im_kos/delphi-cvariants
Связался по QQ китаец, помог пофиксить старые баги. Теперь форкнул. Таки пригодилось кому–то.
im_kos форкнул репозиторий OCTAGRAM/delphi-cvariants под именем im_kos/delphi-cvariants
Связался по QQ китаец, помог пофиксить старые баги. Теперь форкнул. Таки пригодилось кому–то.
Заказчик хотел возможность копипастить код из обычного приложения в web. Решил это тем, что сделал пул из Data Module. Каждый Data Module содержит все соединения к базе данных, отправлялки e-mail и прочие компонентики, скопипащенные из обычного. Для каждого запроса берётся экземпляр этого Data Module, и в нём запускается специальный метод, который все эти компонентики теперь может использовать. Опасался, что из неосновного потока что–нибудь будет работать неправильно, но вроде полёт нормальный.
Вот так понимаешь, насколько хорош AWS. В нём просто нет этих перекодировок, неожиданно происходящих то тут, то там. Да и зоопарк из String, Wide_String, Wide_Wide_String, Unbounded_String, Unbounded_Wide_String, Unbounded_Wide_Wide_String в стандартной библиотеке, оказывается, не так уж плох. Можем работать со строками с любой шириной символа, не будучи вынужденными перекодировать их в UTF-8. По крайней мере, самые базовые операции всегда есть. И библиотеки многие либо работают с последовательностями байтов, либо с юникодом, который появился достаточно давно, в Ada 95 и был в GNAT изначально. Не париться про существование ANSI несколько проще, хотя и всё ещё не так просто, как в node.js, когда console.log() без дополнительных танцев с бубном просто выводит Юникод на любой OS.
Наша компания постоянно мониторит рынок и опрашивает профессиональных разработчиков, чтобы развивать наши продукты в востребованных направлениях. Будущий тренд – это связь облачных технологий, мобильных приложений и интернет вещей. Особенно будет востребована кроссплатформенная разработка и создание связанных приложений. Попробуйте RAD Studio XE7.
Конечно, что же ещё ему советовать? tproger.ru
Using Object Pascal or RIDL Syntax
Наткнулся как–то на сравнение синтаксисов IDL в Delphi, но не смог докопаться, а как работать с паскалевским–то, ведь Delphi моего патриотизма не оценила и показывала только RIDL. Оказывается, даже в XE2 его нету, в документации к Seattle, наверное, забыли убрать, зато в древней Delphi 2007 можно зайти в Tools » Options » Environment Options » Delphi Options » Type Library, переключить Language в Pascal, после этого обычным File » Open… открыть .tlb и переключиться на вкладку Text.
Понадобилось поизучать одну библиотечку без документации, ибо эта библиотечка может потенциально помочь мне поддерживать бинарные форматы, в которых ВУЗы обязаны посылать сведения в РосОбрНадзор. А библиотечка муторная, и в синтаксисе IDL у меня глаза начинают вытекать, вот я и вернулся к этому вопросу и–таки получил её в паскале–подобном синтаксисе.
Можно посмотреть здесь: 1, 2
С документацией на формат XML дела тоже не заладились. Когда–то документацию можно было скачать с сайта госконторы, которая этот формат и делала, а сейчас на её сайте какая–то хрень, и ничего не найти. И на сайте, куда переехал программный пакет GosInsp, тоже не видать.
Наткнулся как–то на сравнение синтаксисов IDL в Delphi, но не смог докопаться, а как работать с паскалевским–то, ведь Delphi моего патриотизма не оценила и показывала только RIDL. Оказывается, даже в XE2 его нету, в документации к Seattle, наверное, забыли убрать, зато в древней Delphi 2007 можно зайти в Tools » Options » Environment Options » Delphi Options » Type Library, переключить Language в Pascal, после этого обычным File » Open… открыть .tlb и переключиться на вкладку Text.
Понадобилось поизучать одну библиотечку без документации, ибо эта библиотечка может потенциально помочь мне поддерживать бинарные форматы, в которых ВУЗы обязаны посылать сведения в РосОбрНадзор. А библиотечка муторная, и в синтаксисе IDL у меня глаза начинают вытекать, вот я и вернулся к этому вопросу и–таки получил её в паскале–подобном синтаксисе.
Можно посмотреть здесь: 1, 2
С документацией на формат XML дела тоже не заладились. Когда–то документацию можно было скачать с сайта госконторы, которая этот формат и делала, а сейчас на её сайте какая–то хрень, и ничего не найти. И на сайте, куда переехал программный пакет GosInsp, тоже не видать.
В Ada каждое объявление типа, подтипа, переменной или константы — отдельный элемент, там просто разрывать нечего.
I’ve Got a Great Ide(r)a – Let’s Buy Embarcadero!
Очередная перекупка Delphi очередной доселе неизвестной, но внезапно, оказывается, достаточно состоятельной для этого фирмой.
Очередная перекупка Delphi очередной доселе неизвестной, но внезапно, оказывается, достаточно состоятельной для этого фирмой.
Project Centennial: Converting your Normal Windows App (Ada, Delphi, SOM) to a Metro Windows App for Distribution in the Windows Store
В Microsoft наконец зачесались, а чёй–то так мало приложений под Metro, наверное, средства разработки были трешовые, значит, надо дать возможность нормальными средствами разработки делать приложения для Metro
В Microsoft наконец зачесались, а чёй–то так мало приложений под Metro, наверное, средства разработки были трешовые, значит, надо дать возможность нормальными средствами разработки делать приложения для Metro
Я грешу на то, что, наверное, uiAccess нужно включить и подпись цифровую сделать. Пожалел, что своевременно не озаботился попросить ключик для цифровой подписи для open source разработчиков, так бы быстро проверил.
Немного про странноватых менеджеров, которые хотят переписать на C++
A new project manager at my company asserts that Delphi can not be used in an FDA approved medical device. Has anyone heard of such a thing; do you have an contra evidence ? He assert the same for Windows Embedded, Linux and C++ is what it must be.…
I don't think he has a basis, other than C++ programmer's distain and disrespect for Delphi plus the desire to do things the way he has done in the past. The Devices are Class 1, with no chance of patient harm. Problem is we have a large code base, developed over 15 years, that according to the project manager must be ported to C++ (at the risk of breaking the bank).…
Your comments that "never been raised as an issue" is what I have heard from others, regulators don't care what language the software is written in.
Thanks for your comments; I'm not sure if I will continue to fight the anti-Delphi biases.
Matt, thanks for your testimonial. I'll add it to my bucket of evidence.…
The 2nd reason my PM says we MUST port to C++ is the difficulty of finding Delphi programmers. There is a grain of truth perhaps to that, but I don't think it should be elevated to a reason to risk the company by undertaking a costly port to C++.
The argument about C++ programmers being more prevalent may be valid (there are other threads that discuss this), but if for the sake of argument we assume that it's true, then his argument is about the tradeoff for the perceived safety of a larger body of programmers at a cost of longer development and debug times. It also harkens back to the old saying (pre-PC days) "No one ever got fired for buying IBM". Your manager may be a CYA type. So it goes.…
The previous product suffered a rewrite into C++ and never came back to life, and still sits in a pile on the floor. One would think people would not repeat the same mistake, but that CEO and PM were fired because of the failure and the new ones have big egos and don't want to hear about history. Go Figure.
bitbucket.org
Году так в 2009м исходя из той картины мира, которой я тогда руководствовался, я считал, что на языке Ада будет здорово писать, если будет полное WinAPI, чтоб и ACL поманипулировать, и оконными сессиями, и в пространство объектов NT забраться можно было. Win32Ada оставляли желать лучшего по охвату современного API. Делать я это намеревался не через сишные заголовки, в которых часть метаинформации безнадёжно потеряна, а вкрутив мозги джедаям. То есть, есть группа JEDI, которая делает неплохие привязки, но вот одна проблема, они это делают для Delphi, а не для Ada. Так как языки похожи, неплохо бы одно в другое сконвертировать, причём, по возможности, автоматом, и не AST в AST, а текст в текст.
Поначалу я пытался наладить конвертацию на препроцессоре GEMA, даже получилось, но это было явно больше, чем на что был расчитан GEMA, да и писать тяжело. Чем более зрелую реализацию пытаешься сделать, тем в большее количество ограничений упираешься. Для тех, кто не знает, там какое–то продвинутое программирование начинает становиться похожим на продвинутое программирование в bash. То есть, мы не можем сделать переменную x ассоциативным массивом, зато можем понаплодить переменных x[*], и работать дальше как будто у нас есть ассоциативный массив.
Решил поискать альтернативу. Смотрел в сторону GPP. Смотрел в сторону Refal. Как остановился на Icon, уже точно и не помню. Примерные соображения таковы, что когда–то раньше мне было интересно, чтобы «for а := 1 to 3 do B;» было не единым узлом синтаксического дерева, а чтоб 1 to 3 сам по себе что–то значил, присваивание было бы таким же присваиванием, как и в других местах, и for мог перебирать не только это, но и другие выражения, и как–то так получилось, что такой язык действительно есть, и так как он по описанию хорошо подходит для обработки текста, и в нём есть backtracking, его и решил взять. Так я и начал писать на Icon. Начало не из лёгких. Одно дело переписать что–нибудь с одного императивного языка на другой (а на Icon можно писать в императивном стиле). Другое дело — нужно было переписать шаблоны. На GEMA уже кое–что было написано, упирающееся в ограничения GEMA, надо было разобраться в Icon и переписать на него. Долго мучился, пока не начал думать «в две стороны». В Icon каждое выражение — это генератор, и функции — это тоже генератор, и особенно важно научиться писать функции, которые не обычные функции, как в императивном языке программирования, а пробуют распознать текст по шаблону и переписать в другой текст, и сами при этом такие же, как они, преобразователи для своей работы используют. Чтобы их писать, надо думать в две стороны: что случится, если выполнение идёт вперёд, и что случится, если начнётся откат.
Переписал. И пошёл дальше этим путём, насколько смог. Времена у меня были не из лёгких, 2005-2010 года самые паршивые в жизни получились, да и сейчас до сих пор не сахар. Довёл до такого состояния:
bitbucket.org
bitbucket.org
У меня на сайте написано:
Это как раз тот случай. «Посмотрел в окно» — и дальше по своим рельсам. Специальность у меня приборостроитель, диплом придётся на левую тему делать, совместить образование с учёбой в очередной раз не получается. Сейчас бы я, впрочем, за кое–что другое взялся.
Когда я пишу про то, чтобы взять Cocoa и GNUStep и сделать мост в SOM, а потом, может быть, и сам GNUStep переделать, это для меня выглядит вполне посильно. Есть BridgeSupport XML, есть опыт преобразования текст=>текст (в том числе #1435793). Самые разые способы достигать этих целей.
Году так в 2009м исходя из той картины мира, которой я тогда руководствовался, я считал, что на языке Ада будет здорово писать, если будет полное WinAPI, чтоб и ACL поманипулировать, и оконными сессиями, и в пространство объектов NT забраться можно было. Win32Ada оставляли желать лучшего по охвату современного API. Делать я это намеревался не через сишные заголовки, в которых часть метаинформации безнадёжно потеряна, а вкрутив мозги джедаям. То есть, есть группа JEDI, которая делает неплохие привязки, но вот одна проблема, они это делают для Delphi, а не для Ada. Так как языки похожи, неплохо бы одно в другое сконвертировать, причём, по возможности, автоматом, и не AST в AST, а текст в текст.
Поначалу я пытался наладить конвертацию на препроцессоре GEMA, даже получилось, но это было явно больше, чем на что был расчитан GEMA, да и писать тяжело. Чем более зрелую реализацию пытаешься сделать, тем в большее количество ограничений упираешься. Для тех, кто не знает, там какое–то продвинутое программирование начинает становиться похожим на продвинутое программирование в bash. То есть, мы не можем сделать переменную x ассоциативным массивом, зато можем понаплодить переменных x[*], и работать дальше как будто у нас есть ассоциативный массив.
Решил поискать альтернативу. Смотрел в сторону GPP. Смотрел в сторону Refal. Как остановился на Icon, уже точно и не помню. Примерные соображения таковы, что когда–то раньше мне было интересно, чтобы «for а := 1 to 3 do B;» было не единым узлом синтаксического дерева, а чтоб 1 to 3 сам по себе что–то значил, присваивание было бы таким же присваиванием, как и в других местах, и for мог перебирать не только это, но и другие выражения, и как–то так получилось, что такой язык действительно есть, и так как он по описанию хорошо подходит для обработки текста, и в нём есть backtracking, его и решил взять. Так я и начал писать на Icon. Начало не из лёгких. Одно дело переписать что–нибудь с одного императивного языка на другой (а на Icon можно писать в императивном стиле). Другое дело — нужно было переписать шаблоны. На GEMA уже кое–что было написано, упирающееся в ограничения GEMA, надо было разобраться в Icon и переписать на него. Долго мучился, пока не начал думать «в две стороны». В Icon каждое выражение — это генератор, и функции — это тоже генератор, и особенно важно научиться писать функции, которые не обычные функции, как в императивном языке программирования, а пробуют распознать текст по шаблону и переписать в другой текст, и сами при этом такие же, как они, преобразователи для своей работы используют. Чтобы их писать, надо думать в две стороны: что случится, если выполнение идёт вперёд, и что случится, если начнётся откат.
Переписал. И пошёл дальше этим путём, насколько смог. Времена у меня были не из лёгких, 2005-2010 года самые паршивые в жизни получились, да и сейчас до сих пор не сахар. Довёл до такого состояния:
bitbucket.org
bitbucket.org
У меня на сайте написано:
Хочу как вот этот парень (Л. Поттеринг), и есть идеи, чем бы я мог заняться, а получается так, что мой поезд жизни едет и едет по своим рельсам, а мне только и остаётся, что жадно смотреть в окно.
Это как раз тот случай. «Посмотрел в окно» — и дальше по своим рельсам. Специальность у меня приборостроитель, диплом придётся на левую тему делать, совместить образование с учёбой в очередной раз не получается. Сейчас бы я, впрочем, за кое–что другое взялся.
Когда я пишу про то, чтобы взять Cocoa и GNUStep и сделать мост в SOM, а потом, может быть, и сам GNUStep переделать, это для меня выглядит вполне посильно. Есть BridgeSupport XML, есть опыт преобразования текст=>текст (в том числе #1435793). Самые разые способы достигать этих целей.