Свершилось. Lazarus 1.0 релизнулся. Поздравляем команду работавшую над этой замечательной средой со столь важной вехой. Буду постепенно адаптировать свои наработки под FreePascal, чтоб в перспективе полностью слезть с Delphi. Абракадабра, похоже, совсем берега потеряла.
четверг, августа 30, 2012
среда, июля 18, 2012
Евангелисты врут. FireMonkey - отстой.
Вы, наверное, в курсе, что Embarcadero активно продвигает свое новое видение создания кроссплатформенного гуя – FireMonkey (они это называют фреймвоком, но для её нынешнего состояния это слишком круто звучит). В рунете анонсируется один конкурс за другим, проводятся вебинары, и пусть качество последних оставляет желать лучшего, но активность радует. Теперь, собственно, к теме. В рамках последнего конкурса было предложено разработать какое-нибудь приложение для обучения. И вот вчера появилась очередная работа за авторством Евгения Чмеля (не знаю, склоняется эта фамилия или нет). В отличии от виденных ранее, простеньких “одноформочек”, тут была сделана попытка подергать обезьяну за все конечности: стилизация, 3D, шейдерные эффекты (о GPU accelerated graphics очень любят говорить евангелисты Embarcadero :)) ). Давайте посмотрим, что из этого вышло. Для тех, кто не смотрел вебинары сделаю маленькое отступление. На одном из вебинаров, евангелист Embarcadero, Всеволод Леонов рассказал душещипательную историю о том, как ему пришлось “компьютер перегрузить, конкретно, жестко” (это цитата), из-за того, что Silverlight SDK и эмулятор Windows Phone 7 “не cработали” (это цитата) на его компьютере т.к. им не понравился видеоадаптер или настройки графического процессора. А вот приложения разработанные с использованием FireMokey, продолжает Всеволод, совершенно не требовательны к аппаратному обеспечению. Давайте посмотрим, как он нам врал. Беспристрастным свидетелем нам будет Process Explorer v15.05 от Марка Русиновича. Итак, качаем приложение Евгения и запускаем (скриншотов приложения Евгения не привожу, они есть по ссылке на его работу. Обратите внимание на размытость шрифтов).
Запустили приложение. Смотрим на потребление:
Нескромно, но можно простить “передовой технологии”. Переходим к разделу “Уроки” и выбираем “Урок 5”. Начинается подготовка сцены. Процесс этот длительный (у меня заняло чуть больше минуты, на четырехядерном Phenom II с частотой 3.3GHz), запаситесь терпением. Сцена построена. Смотрим на потребление:
Обезьяна хорошо подкрепилась. Даже очень хорошо. Теперь попробуйте подвигать мышку над кнопками вариантов ответов. Ощущение, что GUI реагирует ну о-о-очень вяло, не так-ли? Смотрите на график использования CPU (я имею ввиду, что вы должны сами это попробовать, на своем компьютере) – в эти моменты его загрузка приближается к 100% (у меня было ~21.5% для четырехядерного процессора, что эквивалетно 86% для одноядерного). А ведь нам кто-то рассказывал про GPU accelerated graphics. Ладно, идем дальше. Отвечаем на все вопросы урока. Смотрим потребление:
Глаза не округлились? Теперь посмотрите, для сравнения, сколько потребляет 3D-стрелялка FarCry с активным игровым процессом (уровень называется Фабрика, если кому, вдруг, интересно) запущенная в полноэкранном режиме 1440x900:
Выводы делайте сами.
четверг, июля 05, 2012
Delphi XE2 Update 4 HotFix 1. А с дженериками до сих пор проблемы :(
Хотите получить Access Violation на абсолютно ровном месте, без намека на ухабы? Велком, как говорится:
program array_of_generic_record;
{$APPTYPE CONSOLE}
Uses
TypInfo;
Type
TRec<T>
FField : T;
End;
Var
a : Array Of TRec<TObject>
i : Integer;
r : TRec<TObject>
begin
WriteLn(SizeOf(TRec<TObject>
WriteLn(GetTypeData(TypeInfo(TRec<TObject>
SetLength(A, 1000000); // but system.DynArraySetLength.elSize = 1; line 28288
// (DelphiXE2 update 4 hotfix 1); look at attached screenshot: bug.png
// absolutely normal code lead to access violation error
For i := Low(a) To High(a) Do
a[i] := r;
end.
В общем, из описания понятно, что в системном модуле неверно получается размер элемента динамического массива. Из-за чего, понятное дело, памяти выделяется меньше и попытки работать с таким массивом приводят к краху. На дворе 2012 год. Блин, когда они уже нормальный компилятор осилят написать. Лучи ненависти вам, абракадабры :E
p.s. QC #106917
среда, апреля 18, 2012
Firemonkey. Анимммммация.
Полюбуйтесь:
Параметры анимации:
- Продолжительность 0.5 сек
- Стартовое значение 6
- Конечное значение 64
В уголочке приложение работающее под виртуальной машиной с Windows XP и приложение работающее на хост-машине с Windows 7. Приложение пишет в Memo-лог изменения свойства Step на которое настроена анимация.
Обнаруженных косяков два:
- Дважды приходит стартовое значение
- Разное количество “шагов” анимации при идентичных параметрах
А я думаю чего это у меня анимашка так дергается на семерке, и отчего кажется более плавной на виртуализированной XP. Ужас, блин.
понедельник, декабря 26, 2011
понедельник, декабря 05, 2011
Знатные грабельки компилятора
Сегодня налетел на такое:
program nested_exception_class;
{$APPTYPE CONSOLE}
{$R *.res}
uses
SysUtils;
Type
EUnitException = Class(Exception);
//
TMyRec = Record
Type
Exception = Class(EUnitException);
EOtherException = Class(Exception);
End;
//
begin
// ожидается: TMyRec.Exception, в действительности: Exception
WriteLn(TMyRec.EOtherException.ClassParent.ClassName);
// утверждение должно быть истинным, но нарушается
Assert(TMyRec.EOtherException.ClassParent = TMyRec.Exception);
end.
Компилятор выбрал неправильного родителя для моего класса (EOtherException), хотя в редакторе, если кликнуть (Ctrl+Click) по, родителю (Class(Exception)) переход происходит к “правильному” классу (TMyRec.Exception). Баг воспроизводится в Delphi 2006, Delphi XE2 Update 2, промежуточные не проверял, но думаю и там воспроизведется.
пятница, апреля 01, 2011
среда, декабря 01, 2010
Вы все еще верите докам?
Вот что говорит Platform SDK о реализации метода Invoke, в части о возвращаемых значениях, интерфейса IDispatch:
“DISP_E_NONAMEDARGS
This implementation of IDispatch does not support named arguments.”
А вот что говорит система получив DISP_E_NONAMEDARGS:
Eng:
---------------------------
test
---------------------------
No named arguments.
---------------------------
OK
---------------------------
Rus:
---------------------------
test
---------------------------
Именованные аргументы отсутствуют.
---------------------------
ОК
---------------------------
Совсем одно и то же, правда?
вторник, ноября 30, 2010
четверг, ноября 25, 2010
Условная компиляция: defines vs. const
Те кому приходится обеспечивать работоспособность кода на нескольких версиях Delphi не по наслышке знают о “прелестях” условной компиляции. Довольно сложно держать в голове набор фич каждой версии и особенности их работы. Ориентация на CompilerVersion, RTLVersion и VERXXX кажется простым делом в момент написания кода, но превращается в кошмар к моменту его рефакторинга т.к. все детали из головы уже выветрились и скучные выражения вроде {$IF CompilerVersion >= 18.5} ясности не добавляют. Обычно эта проблема решается с помощью включаемых файлов (те, что с расширением .inc), где, основываясь на значениях перечисленных выше сущностей (и возможно некоторых других), создается некий набор определений (defines) с читаемыми именами. Делается это, например, так:
{$IFNDEF FPC}
{$DEFINE DCC}
{$ENDIF}
...
// Anonymous methods
{$IF Defined(DCC) and (CompilerVersion >= 20)}
{$DEFINE HAS_ANON_METHODS}
{$IFEND}Тут мы видим создаваемое определение HAS_ANON_METHODS, которое в дальнейшем позволит нам не вспоминать о версии компилятора, а просто и удобно писать код:
Type
TMyEvent = {$IFDEF HAS_ANON_METHODS}Reference To {$ENDIF}Procedure(Sender : TObject) Of Object;
Но так ли, на самом деле, это удобно? Судите сами. CodeInsight не обеспечивает подсказки для определений. Написав “HAS_” и нажав Ctrl+Space вы не получите весь список возможных определений, а значит снова должны все держать в голове. Это не удобно. Лично меня это просто убивало. Однако, решение есть (для версий Delphi начиная с 2005):
Unit Common.Features;
Interface
Type
//
Delphi = Record
Type
//
Platform = Record
Const
Windows = {$IF Defined(MSWINDOWS)}True{$ELSE}False{$IFEND};
Linux = {$IF Defined(LNUX)}True{$ELSE}False{$IFEND};
MacOS = {$IF Defined(MACOS)}True{$ELSE}False{$IFEND};
{$REGION ' Platform check '}
{$IF Ord(Windows) + Ord(Linux) + Ord(MacOS) <> 1}
{$MESSAGE FATAL 'Unknown platform'}
{$IFEND}
{$ENDREGION}
x32 = SizeOf(Pointer) = 4;
x64 = SizeOf(Pointer) = 8;
End;
//
//
Language = Record
Const
Unicode = {$IF Declared(UnicodeString)}True{$ELSE}False{$IFEND};
Generics = CompilerVersion > 18.5;
AnonymousMethods = CompilerVersion >= 20;
Attributes = {$IF Declared(TCustomAttribute)}True{$ELSE}False{$IFEND};
End;
//
//
RTL = Record
Type
//
TObject = Record
Const
ToString = RTLVersion >= 20;
End;
//
//
ObjectInvoke = Record
Const
MaxParams = {$IF RTLVersion < 20}10{$ELSE}32{$IFEND};
End;
//
End;
//
End;
//
Implementation
End.
Это не законченное решение, пока это только концепт. Надеюсь, основная идея понятна. Небольшой пример кода:
scode := E_FAIL;
bstrSource := {$IF Not Delphi.Language.Unicode}UniUtf8Decode{$IFEND}(ClassName);
{$IF Delphi.RTL.TObject.ToString}
bstrDescription := ExceptObject.ToString
{$ELSE}
If ExceptObject Is Exception Then
bstrDescription := Exception(ExceptObject).Message
Else
bstrDescription := {$IF Not Delphi.Language.Unicode}UniUtf8Decode{$IFEND}(ExceptObject.ClassName);
{$IFEND}
Помимо того, что тут мы сразу видим иерархию (и это очень помогает), нам еще и CodeInsight будет помогать (только за пределами фигурных скобок).
26.11.2010
Забыл написать о самом серьезном преимуществе такого решения. Компилятор контролирует корректность идентификаторов (правда с некоторыми оговорками, но это не важно), и если где-то ошибиться в написании то такой код просто не скомпилируется.
суббота, июня 26, 2010
Generics vs. Inline
Директива Inline не действует на методы в дженериках. Кажется, благое дело обернуть работу с динамическими массивами структурой-дженериком дабы увеличить функциональность путем добавления простых методов Add, Remove, Insert и т.п. Но все благие намерения натыкаются на суровую реальность в которой существует компилятор Delphi :( Столкновение произошло на этапе добавления свойства Items с сеттером SetItem и геттером GetItem, которые, конечно-же, были объявлены как Inline ведь их тела состоят ровно из одной строки (делать проверки индексов в столь тонкой обертке не практично и даже вредно), а вызываться они могут очень и очень часто. После проверки выяснилось, что компилятор не разворачивает тела этих методов, а делает их вызовы :( Можно, конечно, было объявить свойство без сеттера и геттера, но такие свойства не могут быть дефолтными, а значит писать код вида arr[index] := x; уже не удастся.
“Что-же так все неуклюже-то?” © Особенности национальной охоты.
понедельник, января 25, 2010
Ужасы… Windows Platform SDK
Пользовался Windows Platform SDK for Windows Vista. Желая иметь самую свежую документацию скачал новый Windows SDK for Windows 7 and .NET Framework 3.5 Service Pack 1 (Build date: 6/11/2009). Ужас. Смотрим статью о WideCharToMultiByte:
Список кодовых страниц для которых флаги и некоторые параметры должны быть нулевыми.
Список из нового SDK:
- 50220
- 50221
- 50222
- 50225
- 50227
- 50229
- 57002 through 57011
- 65000 (UTF-7)
- 42 (Symbol)
А вот страницы из прежнего SDK:
- 50220
- 50221
- 50222
- 50225
- 50227
- 50229
5293654936- 57002 through 57011
- 65000 (UTF7)
- 42 (Symbol)
Как видим, из нового SDK исчезло упоминание страницы 52936 (54936 упоминается в документации дополнительно). Здравствуйте, грабли!
Теперь сравните описания параметров.
Новый SDK:
Optional. Pointer to the character to use if a character cannot be represented in the specified code page. The application sets this parameter to NULL if the function is to use a system default value. To obtain the system default character, the application can call the GetCPInfo or GetCPInfoEx function.
For the CP_UTF7 and CP_UTF8 settings for CodePage, this parameter must be set to NULL. Otherwise, the function fails with ERROR_INVALID_PARAMETER.
Optional. Pointer to a flag that indicates if the function has used a default character in the conversion. The flag is set to TRUE if one or more characters in the source string cannot be represented in the specified code page. Otherwise, the flag is set to FALSE. This parameter can be set to NULL.
For the CP_UTF7 and CP_UTF8 settings for CodePage, this parameter must be set to NULL. Otherwise, the function fails with ERROR_INVALID_PARAMETER.
И прежний SDK:
For the code pages listed for dwFlags, this parameter must be set to a null pointer. Otherwise, the function fails with ERROR_INVALID_PARAMETER.
For the code pages mentioned in dwFlags, lpUsedDefaultChar must be a null pointer. Otherwise, the function fails with ERROR_INVALID_PARAMETER.
Нужно ли говорить, что информация в новом SDK не соответствует действительности. Здравствуйте, еще одни грабли! Ужас… Как можно верить такой доке? Остается только проверять.
суббота, октября 31, 2009
Delphi 2010. Быдлокод
Юнит DBXJSON.pas. Я вообще в ауте...
class function TJSONString.Hex(const Digit: Integer): Byte;
var
HexData: TBytes;
begin
SetLength(HexData,16);
HexData[0] := Ord('0');
HexData[1] := Ord('1');
HexData[2] := Ord('2');
HexData[3] := Ord('3');
HexData[4] := Ord('4');
HexData[5] := Ord('5');
HexData[6] := Ord('6');
HexData[7] := Ord('7');
HexData[8] := Ord('8');
HexData[9] := Ord('9');
HexData[10] := Ord('A');
HexData[11] := Ord('B');
HexData[12] := Ord('C');
HexData[13] := Ord('D');
HexData[14] := Ord('E');
HexData[15] := Ord('F');
Result := HexData[Digit];
end;
вторник, октября 20, 2009
Delphi 2010. System.TObject.GetInterface
Полюбуйтесь на код обеспечивающий проверку идентификатора интерфейса на соответствие "magic GUID" ({CEDF24DE-80A4-447D-8C75-EB871DC121FD}), для безопасного кастинга (TMyObject(TMyIntf)) к объектому типу:
if (Int64(ObjCastGUID.D1) = Int64(IID.D1)) and
(Int64(ObjCastGUID.D4) = Int64(IID.D4)) then
Pointer(Obj) := Self;
И это в системном юните... #78808
четверг, сентября 10, 2009
вторник, мая 26, 2009
Ubuntu 9.04
Четыре дня назад получил по почте новую версию Ubuntu. Итог: оно все лучше и лучше. Несмотря на то, что чего-то не срослось с wubi общие впечатления самые положительные. Очень порадовала, сразу бросившаяся в глаза, качественная настройка саб-пиксельного сглаживания шрифтов. Им бы еще иконки отдизайнить в какой-нибудь конторе, чтоб в едином стиле, да в Гноме немного уменьшить контролы. В общем, мне понравилось :)
воскресенье, мая 17, 2009
#72213 Fixed
На фикс такой очевидной ошибки компилятора потребовалось два месяца... Страшно подумать сколько будут фиксить некорректную инициализацию/финализацию advanced-records, на которую налететь не так просто :( Вот и юзай новые языковые фичи...
вторник, апреля 28, 2009
Три класса секундомеров
Выложен модуль Common.Classes.pas содержащий три класса (advanced-records) секундомеров. TLowResStopwatch на основе GetTickCount, THighResStopwatch на основе QueryPerformanceCounter, и TStopwatch использующий один из предыдущих классов секундомеров в зависимости от аппаратной части компьютера.
вторник, апреля 21, 2009
Исправление в Interface Extender
Исправлена ошибка при работе с динамическим массивом. Проявлялась при попытке добавить несколько интерфейсов на один класс.
понедельник, апреля 20, 2009
Расширенная поддержка интерфейсов для Delphi
В блоге Алексея Тимохина озвучена хотелка касающаяся поддержки интерфейсов базовыми классами. На мой взгляд, идея весьма спорная, во всяком случае при нынешнем положении дел в языке. Однако, реализовать нечно подобное можно уже сейчас ;) Тут я набросал пример, как это может быть реализовано (intfExtender.pas реализует непосредственно механизм расширения, а unit1.pas содержит два примера). Если кому пригодится, буду только рад ;) Универсальность прикладного кода, о которой говорит Алексей, таким образом можно обеспечить.
p.s. Модуль сильно не тестировался, посему никаких гарантий если что ;)
среда, апреля 15, 2009
Очередные ошибки инициализации/финализации в Delphi 2006 - 2009
Отчет #73008 описывает несвоевременную финализцию энумератора являющегося интерфейсом при использовании в основном теле программы (в процедурах и функциях работает нормально), что в некоторых случаях может приводить к ошибкам доступа (Access violation).
Отчет #73009 описывает неадекватную инициализацию (а точнее ее отсутствие) интерфейсного поля advanced record в случае, когда последняя используется в качестве возвращаемого значения.
пятница, апреля 10, 2009
Утечки и неадекватное поведение Delphi 2006 - 2009 Update 1
При передаче advanced record имеющей интерфейсное поле, в качестве константного параметра, есть немалый шанс налететь на утечку и получить неадекватное поведение т.к. даже константный параметр имеющий размер поинтера передается по значению. Подробности и код в отчете #72878
понедельник, марта 23, 2009
Неадекватная финализация Advanced records 2006-2009
Новый отчет за номером #72410 описывает неадекватное поведение финализатора при использовании advanced records.
суббота, марта 14, 2009
Ошибка компиляции на ровном месте
Если у класса или записи определить вложенный энумератор, который будет иметь поля "управляемых" типов (string, interface, dynamic array, variant), то при попытке использования в операторе for-in-do мы получим ошибку компиляции на несоответствие типов. Воспроизводится, и на Turbo Delphi Explorer, и на Delphi 2009 Update 1. Репорт #72213.
понедельник, февраля 02, 2009
Обновлен Common.Encodings.pas
На домашней страничке выложен обновленный Common.Encodings.pas
Добавлены классы кодировок UTF-32 и UTF-32BE (только Delphi 2009), добавлен метод определения кодировки по BOM. Добавлены функции-аналоги WideCharToMultiByte и MultiByteToWideChar для кодировок UTF-16, UTF-16BE, UTF-32, UTF-32BE. Функции приведены к единым сигнатурам. Определен процедурный тип с сигнатурой кодирующей и декодирующей функций. Добавлен воркараунд для корректного определения доступности кодировок UTF-7, UTF-8 под Windows NT 4.0
суббота, января 31, 2009
Утечки на интерфейсных параметрах
Теряются объекты передаваемые в качестве параметров интерфейсных типов в случае, когда не происходит кастинга с проверкой (as) к определенному интерфейсу. Для кода:
Test(TMyObject.Create('1')); // will not be destroyed
Test(IInterface(TMyObject.Create('2'))); // will not be destroyed
Test(TMyObject.Create('3') As IInterface);
утечки будут в первых двух вызовах. Воспроизводится, и на Turbo Delphi, и на Delphi 2009. Отчет #71015.
пятница, января 16, 2009
QC, в чем магия?
Только вчера "ругался" на неторопливость правки багов в компиляторе, а сегодня глянул на свой отчет №70529 и удивился -- он получил статус Internally Opened (как я понимаю, над ошибкой уже работают). Так вот, в чем магия? Неужели голос Алексея был решающим? ;)
четверг, января 15, 2009
Ошибка в Delphi 2009 Update 1
Передача односимвольной строки в диспетчеризируемый метод приводит к передаче кода символа, а не строки. Лечится приведением строки к строке :) т.е. вот так: String('1'). Репорт номер 70529, поддержите, кому не лень.
пятница, ноября 07, 2008
пятница, октября 31, 2008
Приемчик
Потребовалось символ юникод строки проверить на предмет вхождения в суррогатную пару (а конкретно, является ли символ младшим суррогатом). Все бы ничего, но индекс символа вычисляемый и вычислять его для каждого сравнения (коих собственно два) не кошерно. Есть варианты решения:
1. Сохранить индекс в переменной. Просто, но нужна переменная.
2. Сделать функцию и заинлайнить ее. Нужна функция.
3. Извернуться.
Собственно, я о третьем варианте:
With WordRec(AContent[ACharIndex + CharCount]) Do
If (Word(Bytes) >= $DC00) And (Word(Bytes) <= $DFFF) Then;
воскресенье, октября 26, 2008
Оперативность QC
Все шесть моих репортов прошли во внутреннюю базу в среднем через 2 недели после подачи. Шустро. Правда с одним лажа вышла, отрепортил о баге пофикшеном в релизе :(
пятница, октября 10, 2008
Полный QCец...
Только я отрепортил о нескольких ошибках, как меня снова перестало пускать к сервису... Плавающие баги, они самые милые, ага :)
p.s.
Ой блин... Снял галку DN Authentification и все снова заработало. Сплошные воркараунды :))
среда, октября 08, 2008
Я победил QC :)
понедельник, октября 06, 2008
Val в Delphi 2009
Знаете как работает Val с юникодом? Рассматриваются лишь младшие байты символов :( Для проверки прогоните цикл от lo(Char) до high(Char) и посмотрите, сколько символов будет "успешно" преобразовано в число. Грустно. Если кто-то это читает, заQCите плиз...
пятница, октября 03, 2008
Обновился Common.Encodings
В метод GetEncoding добавлен параметр со значением по умолчанию позволяющий указывать на возможность использования стандартных (определенных в классе TEncoding) кодировок. Скажем, код GetEncoding('utf-16') создаст новый объект класса TUnicodeEncoding, а код GetEncoding('utf-16', True) вернет существующий объект TEncoding.Unicode;
понедельник, сентября 29, 2008
Косяк в TEncoding.FreeEncodings;
Не освобождается объект кодировки UTF7. И когда я только QC буду побеждать... :)
воскресенье, сентября 28, 2008
среда, сентября 24, 2008
Delphi 2009 aka Tiburon. TEncoding.
На домашней страничке выложен модуль Common.Encodings расширяющий возможности стандартного класса TEncoding. Модуль содержит class helper для TEncoding и несколько вспомогательных advanced records.
Примеры использования:
1.) Перечисление доступных кодировок
Var
ei : TEncodingInfo;
Begin
For ei In TEncoding.Encodings Do
If ei.IsAvailable Then
WriteLn('codepage: ', ei.CodePage, ' name: ', ei.Name);
End;
2.) Создание кодировки по имени:
TEncoding.Encodings.ByName('utf-16').GetEncoding;или
TEncoding.GetEncoding('utf-16');3.) Создание кодировки по номеру кодовой страницы:
TEncoding.Encodings.ByCodePage(CP_UTF16_BE).GetEncoding;
или
TEncoding.GetEncoding(CP_UTF16_BE);
4.) Получение информации о существющей кодировке:
With TEncoding.UTF8.GetInfo Do
WriteLn('codepage: ', CodePage, ' name: ', Name, ' display name: ', DisplayName);
пятница, сентября 19, 2008
Delphi 2009. Вкратце.
Юникод+дженерики+анонимные методы это все понятно.
Порадовала скорость среды! И особенно скорость CodeInsight (несмотря на то, что я его все равно всегда отключаю)
Наконец-то они научились различать Implicit и Explicit для записей в нативе (2007 не пробовал, может и там уже было). Но вот редактор сильно подкачал, разучившись (в 2006 он и не сильно-то умел) перемещаться по Ctrl+Shift+Up/Down между декларацией и реализацией перегруженных операторов записи (правда, я тестировал на 12.0.3155.16733, может в релизе и поправили), а также разучился (для перегруженных операторов опять же) по Ctrl+Shift+C создавать макет метода по описанию.
Появился UInt64 -- беззнаковое 64битное число.
BeginThread и TInterfaceList по-прежнему имеют потенциальные утечки.
Неработает передача Int64 в параметре диспетчеризуемого метода (вызов метода от вариантной переменной). Точнее, если передавать переменную типа Int64 все работает, а если значение Int64(1024) -- нет.
Exception обзавелся потенциальной поддержкой стек-трейсинга, но только потенциальной :)
Очень порадовал {$POINTERMATH}
В комментариях исходников встречается sysmac.h. Интересно, это то о чем я думаю...?
Порадовал хелпер для TRTLCriticalSection (syncobjs.pas)
Порадовал обновленный ZLib
Огорчает нелепость использования системных InterlockedCompareExchangePointer (и прочих Interlocked...) при наличии нативных в system.pas
Ribbon огорчил неаккуратными скинами (ждем редактора :) или сторонних, качественных скинов) и моргающей отрисовкой. DoubleBuffered Ribbon-контрола не помогает, а буферизовать форму то еще извращение.
TLinkLabel неюзабельна совершенно, т.к. на системах младше XP, линки распознаваться не будут и пользователь будет видеть разметку.
пятница, августа 15, 2008
воскресенье, мая 18, 2008
понедельник, мая 12, 2008
Embarcadero + CodeGear
О покупке CodeGear компанией Embarcadero, стало известно почти неделю тому назад. А вот обращение к клиентам CodeGear, в котором, в частности, говорится о том, что дальнейшая разработка будет нацелена на гетерогенные платформы и различные СУБД. Ребята, идем на Linux и MacOS? :)
четверг, апреля 24, 2008
XML-RPC: Общие ошибки
Одна из самых часто встречающихся ошибок в реализациях XML-RPC -- экранирование лишних символов в строках. Лишних в том смысле, что спецификация XML-RPC их экранирования не требует. Для корректного парсинга пакета требуется экранировать символы: < (<) и & (&). Любые другие символы экранироваться не должны, но очень часто ошибочно экранируют еще и другие символы: ' ('), " ("), > (>).
среда, апреля 23, 2008
Extended RTTI {$METHODINFO ON}
Пару дней назад, налетел на очень интересную граблю. В своем XML-RPC сервере я использую возможность Delphi создавать расширенную RTTI, для регистрации объектов на сервере. Описывается класс с некоторым API, публичная часть (та, что будет доступна XML-RPC клиентам) выносится в секцию Published (для которой и создается Extended RTTI). Затем создается объект данного класса и регистрируется на сервере. В процессе регистрации сервер получает прототипы методов разбирая RTTI. Все работает прекрасно, кроме того, что помимо методов вынесенных в Published, компилятор создает RTTI еще и для некоторых (даже перегруженных!) методов из секции Public. Грабля, вылезла на довольно сложном классе имеющем nested types. На простых классах такого не обнаруживается.
пятница, апреля 18, 2008
Утечка в TInterfaceList
У данного списка (как впрочем и у TList, и его потомков) есть свойство Count позволяющее, как определять количество элементов списка, так и устанавливать его. Очень удобно использовать возможность назначения количества элементов, для многократной очистки списка (т.к. делается это без перераспределения памяти к которому приводит стандартный Clear). Однако, в классе TInterfaceList данная операция приводит к потере ссылок на хранящиеся интерфейсы, следовательно они никогда не будут освобождены.
воскресенье, апреля 13, 2008
XML-RPC. Снова :)
Сегодня получил 5046 вызовов в секунду (и это на отладочной версии, со всеми проверками и ассертами)!
вторник, апреля 08, 2008
Delphi хотелка
Уже который раз ловлю себя на мысли, что очень хочется иметь параметризованные циклы for-in-do. Тогда можно было бы писать примерно так: For Item[Param] In Items Do... Что приводило бы к выборке значений соответствующих параметрам (разумеется, при поддержке перечислителя).
И вторая хотелка касающаяся for-in-do это наличие двух методов вызываемых перед началом перечисления и после. Что помогло бы при реализации перечислителей в виде advanced records, когда им (перечислителям) требуется выполнять некоторые операции (например блокировка/разблокировка) над контейнером.
воскресенье, марта 30, 2008
А знаете ли вы, что...
Операция сравнения AString = '' выполняется в два раза быстрее чем Length(AString) = 0 для AnsiString, и медленнее (примерно в 1.3) для WideString при условии, что строка не пустая.
Плагиат
Какой то пельмень, по имени Max, тырит посты из моего блога (и видимо не только из моего) и публикует на своем (ссылку не дам, ибо нефиг) от своего имени... Этот пост для него.
четверг, марта 20, 2008
Новые высоты :)
Сегодня, после небольшой переделки работы с SAX'ом, получил скорость в 4096 (число-то какое :)) вызовов XML-RPC в секунду (метод без параметров, возвращающий nil)
воскресенье, января 27, 2008
HTML Display Components
Кажется, сабжевая библиотека тихо умирает :( Автор отказывается делать какие-либо изменения/дополнения в будущем.
суббота, января 19, 2008
пятница, января 11, 2008
Ужос, нах...
Вчера, на одном форуме, увидел вопрос дельфиста:
"Раньше использовал инди смтп а как его запихать в поток не знаю. Формы же нет, куда его перетащить можно."
Это было бы смешно, если б не было так грустно :( Остается надеяться, что вот такие кадры, в скором времени, свалят под .Net (а именно такие, в основном, и валят, т.к. Delphi их донимает "акцесс виолатион'ами") и перестанут порочить доброе имя Дельфистов. В результате, свалившие будут писать тормозных и охотчих до памяти монстров (но главное (!), без "акцесс виолатион'ов" :D) на, и без того, тормозящей платформе, а лагерь .Net получит перебежавших чайников, в добавок к родным образованиям :) и постепенно будет ими опорочен :). Аминь.
пятница, января 04, 2008
Очередная бага TAlXmlDocument
Ошибка, иногда, появляется при парсинге документов имеющих комментарии. Воспроизвести ошибку довольно просто -- в цикле создавать и парсить документ, с комментарием переменной длинны, от одного символа до размера буфера. Дело в том, что в процедуре PosInXmlString не учитываются некоторые особенности при расчете смещения. Однако, решить проблему очень просто:
- В процедуре PosInXmlString изменить строку Offset := RawXmlStringLength - RawXmlStringPos{ + 2};
- В процедуре AnalyzeComment добавить условие на размер комментария, длина которого не может быть меньше нуля And (P1 - RawXmlStringPos - 4 >= 0)
четверг, декабря 27, 2007
Проблема скорости TALXmlDocument
В общем, прилетело откуда не ждали :( Пару дней назад решил попробовать отдачу статистики работы сервера XML-RPC в комментарие пакета (т.е. вместо, собственно, комментария отдается XML документ c различными данными). Все бы ничего, да только производительность сервера просела очень значительно... На два порядка, т.е. в 100 с лишним раз. Первым подозреваемым стал именно парсер т.к. непонятки с размером буфера у него уже были. Написал автору -- тишина. Решил сам покопаться в дебрях чужих исходников :). Профайлера нема -- ищем проблему читая код :) Нужно отдать автору парсера должное, он многое сделал для того, чтоб его создание, по скоростным характеристикам, укладывало на лопатки конкурентов :) Там и ассемблерный код, и адаптирующийся под процессор набор процедур/функций для работы со строками. В общем видно, что человек старался. Однако нашел я там и такой код, что просто волосы дыбом и нужного смайла не могу найти. Код приводить не стану т.к. вне контекста (читай метода использования) он абсолютно нормален, скажу лишь, что функция называется CharPosInString. После того, как я ее переписал тормоза сократились в четыре раза (т.е. стало тормозить не в 100 раз, а в 25 :)). Ищу проблему дальше. Меняю размер комментария и вижу, что чем больше комментарий, тем сильнее тормоза. Потом убираю комментарий и добавляю в пакет параметр типа Base64 размером в 64Kb -- снова тормоза. Начинаю грешить на внутренний буфер парсера. После некоторых манипуляций выясняется, что какой бы ни была константа BufferSize, парсер выделяет буфер под самый большой контент встретившийся ему при разборе и потом спокойно работает с этим буфером. Нашел функцию ExpandRawXmlString отвечающую за увеличение буфера при необходимости. В одно из условий добавил несколько строчек и проблема разрешилась (т.е. буффер увеличвается только на время, когда он нужен, а затем возвращается к прежним размерам). В общем и целом, тормоза пропали совсем, но сердцем чую -- нужен профайлер, чтоб найти корень зла тормозящий на любом буфере больше 64 байт :).
пятница, декабря 21, 2007
суббота, декабря 01, 2007
Странный ping. Yandex XML-RPC
Сегодня, от нечего делать, xml-rpc debugger'ом решил дернуть (а вдруг работает) метод system.getCapabilities у сервера Яндекса, который обрабатывает пинги блогов. В ответ меня поблагодарили за пинг и сообщили, что все прошло без ошибок :) Прикольно они там реализовали xml-rpc...
понедельник, ноября 19, 2007
Что-то, как-то...
Ну, совсем меня Ubuntu убила... Вчерась решил заархивировать папку Install весом в 9Gb находящуюся на виндовом ntfs разделе. Не скажу, что в этом была большая необходимость, т.к. архив я предварительно сделал под Windows, просто хотелось посмотреть, как оно в Ubuntu :) Открываю контестное меню на папке Install, выбираю пункт Add to archive (или что-то вроде этого, точно не помню), выбираю тип архива tar.gzip. Отлично! Пошел процесс архивирования. Минут через пять, я решаю прервать это дело. Но не тут-то было... Окошечко, конечно закрылось, но вот индикатор диска продолжал указывать на сильную активность. Подождав еще минут пять, я запустил системный монитор и был несколько удивлен увиденным... В списке процессов преспокойненько болтался процесс tar и явно продолжал архивацию. Я в шоке.
суббота, ноября 17, 2007
Вторые впечатления...
Ох, неоднозначные... Все, вроде, в Ubuntu приятно, но вот словил таки две аномалии. Аномалия первая. Запустил поиск файлов по маске *.png. Файлов нашлось аж 16 тысяч с копейками. Затем, эти найденные файлы, перетаскиваю (drag&drop) в соседнее окошечно с открытой папкой. Все, ОС померла, в смысле впала в состояние анабиоза, в котором только дисковая система продолжала свою активность. Сразу зачах плейер (не помню название, но это тот, из поставки, что с подкастами), перестал двигаться курсор мышки. В общем через некоторое, весьма продолжительное, время диалог поиска файлов самопроизвольно закрылся безо всяких сообщений (так ничего и не скопировалось). Аномалия вторая. Слушая музычку через упомянутый уже плейер, я решил еще помсотреть видео из папки Examples. Запускаю на просмотр видео с Нельсоном Манделлой, и... Это все. Запускается другой плейер и ОС зависает намертво (плейер с подкастами перестает играть). Судя по тому, как зашуршал кулер на проце, чем то ОС его грузила, но прождав минут 10 и не получив ни какого результата я просто выключил буку. Вот такие дела.
среда, ноября 14, 2007
Первые впечатления
Попробовав Ubuntu с LiveCD, я остался очень приятно удивлен качеством дистрибьютива. Имея прежний опыт общения лишь с ASP-Linux (кажется 9.0), могу сказать, что Ubuntu это уже не просто шаг на десктопы пользователей, это полноценный (ну пусть, с некоторыми оговорками) конкурент Windows! Поразила отзывчивость интерфейса при сворачивании/восстановлении окон в момент пиковой загрузки процессора. Кстати, все оборудование моего ноутбука (Toshiba Satellite Pro M30) было определено корректно, и даже noname блютуз донгл определился и заработал. Единственная претензия, так это устойчивое желание Ubuntu ползти в инет, что за драйвером для видюхи (чтоб работали эффекты Compiz Fuzion), что за русским языком для локализации (посмотреть на русский фейс было просто интересно). Возможно, это из-за того, что я использовал LiveCD, а не устанавливал систему на винт. Очень порадовало качество сглаживания шрифтов Subpixel Smoothing, кажется более качественным нежели Windows ClearType. А вот сами шрифты изяществом не блещут. В общем и целом, Ubuntu зачет!
Убунта
Сегодня получил заказанные 09.10 диски Ubuntu! Доставили прямо в почтовый ящик. Теперь буду смотреть :)
среда, ноября 07, 2007
XML-RPC boxcarring 2
Позавчерашний результат в 4500 вызовов в секунду, что-то не очень меня порадовал... По моим прикидкам, должно было работать значительно быстрее. Сегодня начал искать узкое место. Им оказался используемый мною SAX парсер, который сильно тормозил при размере пакета в 2 мегабайта. Порылся в его исходниках (благо, он открытый и бесплатный), и попытался без профилирования определить, где могут быть затыки. Нашел константу BufferSize = 8192 байта. Отлично, подумал я :), сейчас увеличу буфер в два раза и посмотрю. Посмотрел :( Скорость упала вдвое. Я в полнейшем шоке. Решил буфер уменьшить... Скорость возросла :) В общем, я дошел до буфера в 16 байт :) Причем с таким буфером, скорость хорошая, и при парсинге больших строк, и при парсинге файловых стримов (85Мб).
P.S. Руки дойдут, посмотрю на него под профайлером, а пока результат меня удовлетворил -- 16667 вызовов в секунду!
понедельник, ноября 05, 2007
XML-RPC boxcarring
Сегодня протестировал механизм boxcarring'а в XML-RPC. Результат -- ~4500 вызовов в секунду!
пятница, ноября 02, 2007
Delphi-грабельки 2
Ох уж эти грабельки... Сегодня наступил там, где и не ожидалось :( Есть в ObjectPascal чудесная функция Slice, которая возвращает N первых элементов открытого массива и использовать которую можно только, как параметр процедуры или функции. Вот сегодня мне эта радость и понадобилась. Надобность обернулась руганью компилятора о том, что функция используется не по назначению т.е. не в качестве параметра функции или процедуры. Ну, это компилятор так думал... На самом деле, все оказалось проще. Функция, а точнее метод, в который я собирался передать кусочек массива, являлся перегруженным и имел сестру-процедуру принимавшую два параметра, первым из которых должен был быть открытый массив (который, собственно, Slice и возвращает). Такие вот грабельки. Пришлось морщить лоб и выдумывать другое имя для сестры-процедуры :(
среда, октября 31, 2007
Delphi-грабельки
Оказывается, в Delphi нельзя объявить больше одного перегруженного метода в секции Published.
Сегодня я на эти грабельки наступил... Обидно :(
пятница, октября 19, 2007
Набросок XML-RPC сервера
Сегодня сделал таки набросок XML-RPC сервера чтоб оценить скорость работы. В общем скорость получилась потрясающая: 3750 вызовов в секунду! Правда ввиду того, что это лишь набросок, где отсутствует куча проверок, в окончательном варианте цифра будет поменьше. Но думается мне, что не меньше 3500 :)
вторник, октября 16, 2007
XML-RPC хотелка
Очень хочется официального апдейта спецификации XML-RPC с целью добавления 64-битных целых. Не очень радует перспектива передавать такие числа в виде строки/двуэлементного массива/записи с двумя членами. Куда бы написать об этом (?), xmlrpc.com совсем мертв, кажется :(
среда, октября 10, 2007
Семь нянек
Сегодня бегло полистал вот эту книгу:
Programming Web Services with XML-RPC
Simon St. Laurent
Joe Johnston
Edd Dumbill
Publisher: O'Reilly
First Edition June 2001
ISBN: 0-596-00119-3, 230 pages
Неоднозначные впечатления... Прям на 24 странице, в пункте 2.3.1.1 Parameters присутствует фраза "Even if the method requires no parameters, the <params> element must still be present." противоречащая спецификации XML-RPC. Вроде и авторов аж трое, а такой косяк допустили. Немного ранее авторы сделали смелый вывод о том, что дубликаты членов структуры запрещены т.к. они (авторы), в противном случае, не могут понять, как может интерпретироваться подобная структура :)
В общем, книга мне не очень понравилась. Какая-то однобокость суждений ощущается.
вторник, октября 09, 2007
Убунта
Сегодня оформил пред-заказ на 2 (32+64 bit) CD Linux Ubuntu 7.10. Интересно, сколько диски будут добираться до меня и действительно ли все будет бесплатно... Решил FPC 2.2 под линуксом посмотреть :)
пятница, сентября 21, 2007
Рекорды скорости
Не то, чтобы я специально подтачивал библиотеку для достижения высоких результатов, просто в следствии совсем крошечной оптимизации удалось получить уже 2583 вызова в секунду :) без модификации серверного компонента.
понедельник, августа 13, 2007
Скорость передачи данных в XML-RPC
Сегодня продолжил тесты на локальной машине. На этот раз решил проверить чистую скорость передачи данных (как если бы передавался файл). В результате, скорость чуть больше 13Мб в секунду! Передавались блоки по 32Кб, в единственном параметре метода, тип Base64 (т.е. реальный блок получался ~43Кб. Не стоит забывать, что спецификация XML-RPC разрешает использовать и строки для передачи бинарных данных). Выходит, что файл размером в 130Мб был бы передан за 10 секунд. Если блоки передавать строкой, а не Base64, скорость получается 28.5Мб в секунду :)
Было желание попробовать этот тест с использованием gzip-сжатия, но мне стало лень прикручивать фильтр к IIS :)
суббота, августа 11, 2007
Скорость XML-RPC
Сегодня протестировал свою библиотеку XML-RPC на локальной машине (до этого тестировал только при нахождении сервера под виртуалкой). Сервер IIS 5.1 под которым работает мой xml-rpc ISAPI. Клиент -- Delphi-приложение. Клиент вызывает метод currentTime.GetCurrentTime возвращающий текущую дату и время. Многократные замеры показывают результат в 2560 вызовов в секунду (и это без использования boxcarring'а и на неспециализированном сервере)!!! Кто там говорил, что XML-RPC не эффективен ;)
воскресенье, августа 05, 2007
Цвет затемнения в Smoke-screen
Для себя выбрал оптимальный вариант подбора цветов затемнения. Изначально использовал не черный, а очень темно-серый (RGB: 32, 32, 32). Сейчас выбираю цвет в оттенок обоя рабочего стола, т.е. если на обое преобладает зеленый цвет, я немного усиливаю этот цветовой канал (скажем RGB: 32, 48, 16) и ослабляю другой. В результате затемнение ощущается этаким, продолжением обоя :)
четверг, августа 02, 2007
"Турба", ты меня удивляешь...
Сегодня у меня получилось создать объект абстрактного (!) класса... Глюк плавающий и воспроизведению, что-то не поддается.
воскресенье, июля 22, 2007
среда, июля 18, 2007
Снова баг TurboDelphi/BDS2006
Не помню, может я уже писал об этом, просто позавчера снова напоролся... Имеем свойство интерфейсного типа. Имеем сеттер получающий константный параметр (новое значение св-ва ес-но). Внутри сеттера выполняем проверку поддержки необходимого нам интерфейса средствами Supports(Value, IMyInft); Все. После отработки сеттера, мы теряем интерфейс. Баг обходится либо, отказом от константного параметра либо, проверкой интерфейса расширенной версией Supports с дополнительным параметром. Интересно, в D2007 это воспроизводится?
воскресенье, июня 24, 2007
ControlHooks
На домашней страничке выложены модули (D2006/Turbo ~15Kb) позволяющие создавать классы-ловушки элементов управления (потомки TControl), а также пример использования (класс-ловушка обеспечивающий принятое в Windows поведение элементов управления Edit и Combobox при статусах Disabled и ReadOnly).
пятница, июня 15, 2007
UIB 2.1 Release
Почти неделю назад вышел релиз 2.1 чудесных компонентов для прямого доступа к IB/FB/Yaffil
воскресенье, июня 10, 2007
Synapse
В модуле blcksock.pas включена директива {M+}, соответственно все классы библиотеки получают RTTI т.к. имеют published-члены. Не знаю, с какой целью автор это сделал (может для Lazarus'а. Кажется, я что-то слышал об этом), но я, для win32, директиву отключаю.
пятница, июня 01, 2007
Решение с null-stream
Собственно, ничего нового и оригинального я не напишу, но вдруг, кому пригодится :). Есть у меня класс TXmlRpcPacketGenerator, который формирует XML-RPC-пакет в соответствии с параметрами и опциями форматирования (отступы, декларация, варианты компактности). Формирование пакета происходит только в поток т.е. в объект-наследник класса TStream. Встала задача, определения размера будущего пакета ДО его формирования. Было несколько вариантов решения, но остановился я на т.н. null-stream. Создается класс TNullStream(TStream), в котором перекрываются методы Read, Write и Seek. Что делают эти методы понятно из их названия и в контексте названия потока т.е. ничего не делают :), а просто манипулируют счетчиком. Потом в такой поток формируется пакет и задача решена :)
Замечания относительно скорости: самая тяжелая операция в формировании XML-RPC-пакета - кодирование Base64, однако на это можно не обращать внимания т.к. по моим замерам (и моим-же кодером) строка, общим объемом, в 18Mb кодируется всего за 0.25 секунды (PM-1.7Gh 512RAM) (но это время только чистого кодирования). Другая тяжелая операция - это большое количество данных примитивных типов (массивы чисел, дат, булевых и т.п.), однако и это не так страшно, например массив из 100.000 структур формируется за 0.2 секунды и имеет размер 2.4Mb.
вторник, мая 22, 2007
Надоело читать про iso8601
вторник, мая 15, 2007
Colocation заблаговременно...
воскресенье, апреля 22, 2007
Маленький хинт :)
Часто в работе приходится использовать сторонние библиотеки (хотя это можно отнести и к своим) имеющие директивы условной компиляции и соответствующие определения. Это здорово, это позволяет гибко, под нужды приложения, компилировать библиотеку (например я, в UIB включаю UIB_NO_COMPONENT, чтоб предком всех классов стал TObject). Это хорошая практика, но она имеет недостатки: когда происходит обновление версии библиотеки, старые определения (в файлах .inc) могут быть утеряны, не всегда-же все держится в голове. А если таких библиотек несколько? В общем, я для себя нашел способ избавиться от этой головной боли :) В отдельный модуль, или файл проекта (а вообще, куда угодно) подключаются файлы определений (*.inc) библиотек и создаются директивы условной компиляции (пример для UIB):
{$IFDEF DLLREGISTRY}
{$MESSAGE FATAL 'Отключить $DEFINE DLLREGISTRY (jvuib.inc)'}
{$ENDIF}
{$IFNDEF FB20}
{$MESSAGE FATAL 'Включить $DEFINE FB20 (jvuib.inc)'}
{$ENDIF}
{$IFDEF UIBTHREADSAFE}
{$MESSAGE FATAL 'Отключить $DEFINE UIBTHREADSAFE (jvuib.inc)'}
{$ENDIF}
{$IFNDEF UIB_NO_COMPONENT}
{$MESSAGE FATAL 'Включить $DEFINE UIB_NO_COMPONENT (jvuib.inc)'}
{$ENDIF}
Теперь уж точно ничего не забудется при обновлении :)
пятница, марта 16, 2007
OLE automation
Никогда не любил эту штуку. Не, ну здорово, конечно, в Word'е страничку иль в Excel'е табличку/отчетик заделать, но чтоб постоянно использовать - боже упаси. Однако решил, заради эксперимента, прикрутить к своей реализации XML-RPC вызов методов сервера через механизмы диспетчеризации (IDispatch). Надумано - наделано :) Вчера закончил. Результаты, честно говоря, меня очень порадовали. Прямой вызов метода выигрывает у своего диспетчеризуемого аналога всего 0.2 секунды при 10.000 итераций (т.е. разница в пересчете на одну итерацию сопоставима с погрешностью замеров). Проигрывая при этом, по простоте (правда не сильно) и читабельности кода:
Прямой вызов:
For SIndex := 1 To 50 Do
Memo1.Lines.Add(SysUtils.Format('%d - %s', [SIndex, Call('examples.getStateName', [SIndex])]));
Диспетчеризуемый вызов:
For SIndex := 1 To 50 Do
Memo1.Lines.Add(SysUtils.Format('%d - %s', [SIndex, Server.examples.getStateName(SIndex)]));
пятница, марта 09, 2007
Однако, Linux...
Вчера и сегодня в новостях "Компьютерры" мелькнули сообщения о том, что Dell и HP будут поставлять компьютеры с Linux... Интересное кино.
четверг, февраля 22, 2007
Идеальное хранилище
воскресенье, февраля 18, 2007
Очередной баг
четверг, февраля 08, 2007
POPFile 0.22.4. Осьминог жукастый
Где-то, на просторах инета наткнулся на классификатор почты, POPFile, использующий теорему Байеса (Bayes) для отделения мух от котлет :) Нашел несколько хвалебных отзывов от его пользователей (говорят фильтрует аж 99.9% процентов спама), и самое главное, увидел, что он имеет XML-RPC API для взаимодействия с внешним миром. Не смог пройти мимо и не попробовать "повзаимодействовать" :) Качнув и установив его на виртуальную машину, активировал работу XML-RPC API для внешних подключений (по умолчанию XML-RPC отключен). Дело за клиентом! По первому попавшемуся примеру сваял маленький пробник для перечисления корзин классификатора. И тут меня ждал неприятный сюрприз... Ошибшись в имени метода (пропустил одну букву) я получил в ответе некорректную (не соответствующую спецификации XML-RPC) fault-структуру, где член faultCode имел строковый тип... Выходит, используемая им перловая реализация (XMLRPC::Lite если я не ошибаюсь) кривая, коли допускает подобные вольности. Вот такие дела, авторам отпишусь :)
P.S. Вот и делай людям добро ;) Попытался отрапортовать об ошибке, так оказалось, для этого еще и на SourceForge'е нужно регистрироваться. Ну уж нет :)
P.P.S. На вызов метода release_session_key отдается структура, также не соответствующая спецификации XML-RPC (тэг <params> не имеет обязательных дочерних элементов).
вторник, февраля 06, 2007
Неудавшийся поиск
четверг, февраля 01, 2007
"Приведение" типов
Правда не совсем приведение... Встала задача получить из TMemoryStream строку. Самый простой путь, он же и самый не эффективный, задать строке размер SetLength и потом просто скопировать память с помощью Move. Неэффективность налицо: двукратно увеличеное требование к памяти и время на копирование. Но есть вариант проще:
Type
TOpenedMemoryStream = Class(TMemoryStream);
Var
Data : PChar;
...
With TOpenedMemoryStream(AStream) Do
Begin
// Если выделенной памяти ровно столько сколько требуется потоку
// (обычно больше т.к. память выделяется блоками по 8192 байт)
// увеличиваем количество выделенной памяти не изменяя размера потока
If Capacity = Size Then
Capacity := Capacity + 1;
// Сразу за блоком, занимаемым потоком, записываем признак конца строки
// и сохраняем указатель на блок памяти для для последующей обработки
PByte(Integer(Memory) + Size)^ := 0;
Data := Memory;
End;
Теперь переменную Data можно приводить к строковому типу :)
Исходники
четверг, января 25, 2007
День под знаком "петли"
вторник, января 23, 2007
Наследование записей
Ну не так, чтоб уж совсем наследование, но механизм расширения функционала рабочий. Итак: определяем запись TRecord с неким множеством методов. Затем (типа наследуемся) определяем запись TRecordDesc = Type TRecord. Теперь эти записи не совместимы (для чего это нужно - ниже). Описываем Record Helper For TRecordDesc с неким множеством методов/свойств. В итоге, мы получили функционально расширенную запись, ну а несовместимось нужна была, чтоб члены record helper'а не попали к предку. Однако копирование записи достигается простым приведением типа ;) Если бы хэлперы позволяли описывать перегрузку операторов, можно было обойтись и без приведения.
Однако есть еще способ ;). Можно использовать агрегацию, тем самым избавиться от хэлперов и приобрести возможность перегружать операторы :).
понедельник, января 22, 2007
Где, блин, революция!?
Еще, когда только планировалась к выходу Delphi 6, весь инет шумел о веб-сервисах, все говорили, что вот, грядет оно, светлое будущее. И собственно где? Ну блоги, понятное дело, ну еще г-н Орейли чего-то там сделал, ну да, г-н Виннер, а еще? Публичных веб-сервисов кот наплакал, да и те умеют лишь рапортовать о валюте, времени да погоде... Это я к чему, да просто г-н Балмер недавно снова предсказал революцию веб-сервисов в течении ближайших 10 лет :).
Что еще интересно, по задумке идеологов, веб-сервисы должна была объединить одна важная особенность - протокол взаимодействия (тогда на это точили SOAP, а Borland даже сделала RTTI для интерфейсов в шестой версии). И взгляните, что происходит сейчас: образовалась целая куча подходов к осуществлению взаимодействия (SOAP, XML-RPC, REST, JSON, PI-RPC, AJAX и.т.д), каждый считает себя самым умным и делает то, что считает нужным. Например контора на "Г" прибила бету поискового сервиса на SOAP, и перевела его на AJAX (чего уж не на GData). Таже контора обещает отломать от Blogger'а XML-RPC API и перейти на что-то свое... Короче, разброд полнейший... Что-же касается SOAP, то он уже давно превратился в монстра с которым, никому, кроме породивших его Франкенштейнов, связываться не хочется.
воскресенье, января 14, 2007
Что делают в армии?
На этот вопрос каждый отвечает себе сам :) Я пошел в армию вполне осознанно, бросив учебу в университете. Пошел, потому что так было надо (ну воспитывали нас так), т.е. все нормальные косили, а остальные шли служить. До этого я учился в техническом лицее, где получил диплом программиста и к тому времени писал на Clipper'е, Turbo Pascal'е и Assembler'е. Имея первое место "на республике" по программированию, и соответствующий диплом, я наивно полагал, что в армии тоже буду программировать :) Но так в общем и вышло ;) Служил я в РВСН в/ч 44200, прикомандированным к центру психологической работы. Программировал в основном психологические тесты разных мастей по именитым методикам, но такая работа мне не очень нравилась, хотя и напрягала не особенно. Но кроме этого довелось мне писать две интересные программы: первая - расчет заработной платы военнослужащих, а вторая - мой дембельский аккорд (оптимальное распределение военнослужащих). О второй писать не буду т.к. писать придется слишком много :) Ну а первая, вот она:
Написана на Borland Pascal 7.1 with objects. Работала под DOS, в режиме 640 x 480 x 4. В качестве базы данных использовался самописный движок для работы с .dbf (это была моя дипломная работа в лицее). Для программирования интерфейса импользовалась также самописная библиотека. Жаль, что в то время, я ни как не мог въехать в прелесть ООП и библиотека по сути состояла из объектов, но представленных весьма специфично ;) (т.е. каждый объект был записью которая манипулировалась неким множеством процедур и функций). Программа расчета
имела возможность создавать архивные копии данных при переходе на новый месяц, была предусмотрена система справочников, а для простоты изменения алгоритма расчета мне пришлось добавить поддержку формул, для чего был написан синтаксический анализатор (как же мне было трудно и интересно ;))
По интерфейсу было решено закосить под недавно вышедшую Windows 98, отсюда и название такое ;) Мне даже было не влом сделать поддержку цветовых схем аля Windows (см. следующий скриншот)
Программа получилась даже очень ничего ;) и была внедрена в одной из воинских частей, за что я был премирован новой шоколадной "афганкой" (кто служил тот поймет ;) Вот этим я занимался в армии :)
пятница, января 12, 2007
Ностальгия...
Сегодня наткнулся на скриншоты своей (ну писал-то я ее не один, нас было двое, но скрины только моего творчества ;)) первой и единственной корпоративной (как это модно сейчас называть) системы. Чего-то воспоминания нахлынули... В общем вот:
Это диалог регистрации пользователя в системе, где помимо обычных в этом деле полей можно было указать еще псевдоним базы данных к которой будет производится подключение. Это было очень удобно для разработки (а она непрерывно велась в процессе эксплуатации системы) т.к. все спорные моменты и приемы отлаживались на тестовой базе, а при опасных манипуляциях можно было подключиться и вовсе к резервному серверу :).
Далее опишу, как происходило обновление клиентских приложений. Ввиду того, клиентские места были очень сильно разбросаны территориально (удаленные цеха, промыслы. самый дальний ~120км), проблема обновления ПО не решалась методом беготни с дискеткой по офисному зданию. Поэтому соответствующий функционал был заложен в серверную часть еще на стадии проектирования. Реализовано все было очень просто: сервер имел самые последние версии исполняемых модулей, разработчик делая билд (т.е. увеличивая версию) при подключении к серверу публиковал измененный модуль. Когда клиент подключался к серверу, тот проверял версии модулей клиента и имеющиеся у него новые и в случае необходимости, клиенту сливались обновленные версии.
Процесс публикации отражен на следующем скрине:
Это не боевой сервер, скрин был сделан специально для демонстрации состояний клиентских подключений. В динамике все выглядело очень эффектно :), при каждом новом запросе, мониторчик клиента мигал, было сказачно красиво ;).
Моим первым приложением был "Электронный табель" позволявший на местах (в цехах, на промыслах) вести электронный учет рабочего времени, что позволяло отделу кадров оперативно отслеживать ситуацию на рабочих местах и вносить соответствующие коррективы. Но скрина этого приложения у меня не сохранилось, вместо него публикую скрин приложения "Отдел труда и зарплаты", которое полностью повторяло функционал ведения табеля, но кроме этого делало еще массу полезных вещей :). На этом скрине видно большое меню, которое формировалось (т.е. выполнялся весьма приличный запрос к серверу и по результатам строилось меню) в момент клика пользователем на соответствующем пункте. Работало очень даже шустро :)
Затем было написано приложение "Банковские операции", но его скрина у меня тоже не сохранилось. После отработки по банкам, я сел за приложение "Кассовые операции", скрин которого приведен ниже. Это было достаточно простое приложение, но в нем был один интересный (в то время) для меня момент: его нужно было интегрировать с веб-сервером разработчиков (т.е. не корпоративным, а именно девелоперским, т.е. нашим) т.к. на сервере работал скрипт завязаный на сторонний софт, и тащить тот софт на клиента не было ни какого желания (это только добавило бы головной боли). Почему именно веб? А почему нет! :)
Затем мне пришлось возвращаться к старой теме (дело в том, что ранее я уже писал для этой конторы сию прилагу, но только под ДОС, и по договору т.е. я там еще не работал) и писать приложение "Подотчет". Изюминкой этой работы для меня стала реализация "мультиформенного" приложения т.е. приложения без главной формы (office2000 like). Решилась проблема достаточно просто и эффективно, правда пришлось сильно попотеть изучая механизмы взаимодействия различных частей VCL, чтоб обеспечить корректность работы в таком режиме. Особенно это касалось модальности окна только для активной формы.
Ну и наконец скрин боевого сервера. На скрине открыт диалог настройки с назначением прав пользователя. Пользовательская база была интегрирована с базой MS-SQL на котором и крутилась вся система. На SQL сервере было всего 25 лицензий, но за счет серверной части нашей системы (т.е. по сути ее второго уровня) на этих лицензиях работало ~70 целовек :) (я делал стресс-тестирование, сервер выдержал 150 подключений, но не выдержала моя рабочая машинка :)) Я тогда считал, мы экономили для конторы примерно $20К :) (сейчас вероятно цена уже не актуальна). Сервер вел подробнейшие логи работы пользователей, все запросы падали в лог, поэтому мы всегда могли отыскать любые концы :) (и это было важно ввиду некоей борьбы между двумя отделами). Т.к. система работала на BSS (Borland Socket Server) (знаю, что плохо, но это был единственный приемлемый вариант) у нас были частые проблемы с обрывами связи (т.к. сам BSS кривой, да и инфраструктура нашей сети была далека от идеала), поэтому в серверную и клиентскую части был добавлен функционал обеспечивающий механизм сессий и решавший таким образом проблемы с обрывами.
Кроме перечисленных, были написаны и другие приложения, скорее для разработчика нежели для пользователя, но из-за их незначительности упоминания они не удостаиваются. Вот :) Писать замаялся ;)
p.s. Еще и армейскую работу вспомнить, чтоль...
четверг, января 11, 2007
Еще один Free
понедельник, января 01, 2007
Снова о пакетах...
На домашней страничке добавлена инструкция по установке пакетов в Turbo Delphi Explorer. 100% работающая, сам пользуюсь.
пятница, декабря 29, 2006
Инструменты, которые Free
Скорее речь даже не об инструментальных средствах разработчика, а о free-софте вообще. После выхода Turbo Delphi Explorer (которая free) у меня появилось желание если не отказаться от проприетарного софта совсем, то хотя бы свести его использование к минимуму. Как раз к этому моменту, вдоволь наэкспериментировавшись с Вистой (коею пользоваться не собираюсь, но в курсе быть нужно), решил начать с чистого листа, т.е. винта :) Вставил рекавери в свою Тошу и согласился на все, что мне предложили ;).
Итак:
- ОС - лицензионная XP Pro SP2.
- Браузер - Опера 9
- Почта - Опера 9
- Качалка - WinWGet (оболочка над консольной wget)
- Аська - QIP
- Блог-клиент - Windows Live Writer
- Музычка - foobar 2000
- Видео - Media Player Classic
- Офис - OpenOffice (мне очень понравился)
- CD писалка - с Тошей в комплекте идет Drag'n Drop CD+DVD (рядом поставил CDBurnerXP 3 Pro)
- CD-виртуализатор - Алкоголь 120% (вечный триал ;) ибо мне хватает 3 дисков из 6 доступных)
- Графика - GIMP, PhotoFiltre, XnView
- 3D - Blender
- Веб-дизайн - Nvu (мне показался удобнее дрима :)
- Виртуалка - Microsoft Virtual PC 2004 (она же free!!!)
- Архиватор - 7zip
- Файл-менеджер - Far
- Файрвол - Jetico Personal Firewall
- Антивирус - Dr.Web CureIT!
- Секурность - TrueCrypt
- Программирование - Turbo Delphi Explorer, Ada GNAT
- СУБД - FireBird (у него же есть embedded версия!!! ;) средство администрирования - IBExpert (для русских free!!!) (смотрел еще на Interbase Development Studio, но что-то она глючновата...)
- Инсталь-мейкер - InnoSetup
- Компоненты - множество бесплатных и разных ;) Условие только одно - наличие исходников. Очень нравятся: Synapse, UIB, ToolBar2000
Чему не нашел замены (может посоветует кто...):
- Macromedia Fireworks (правда я его использовал не по назначению, а именно, как обычную рисовалку (т.е. его веб-ориентация меня мало интересовала). Может глянуть на Inscape или, как его там...)
- AWIcons Pro - отличный редактор иконок
- ReGet WebSynchronizer - отличный синхронизатор (я им бэкапы исходников делаю :)
вторник, декабря 19, 2006
И снова пакеты в Turbo Delphi Explorer
Ранее я уже писал о процессе подключения пакетов в Turbo Delphi Explorer, а теперь выкладываю модуль делающий это без необходимости саморегистрации подключаемых пакетов.