Форум » [x]Harbour » Delphi Run-Time for [x]Harbour (размышления). » Ответить

Delphi Run-Time for [x]Harbour (размышления).

Sergey Spirin: Здравствуйте. Все-таки не покидает меня мысль о том, что было бы очень неплохо организовать Delphi Run-Time для [x]Harbour. В очередной раз мысль вернулась в связи с выходом Delphi2010. В этой версии сняты ограничения по rtti-доступу даже к private-секциям классов и т.д., что делало бы задачу еще проще. Собственно, сейчас пожалуй, я могу четче сформулировать, что я имею в виду, и даже немного проиллюстрировать. Вообще, предоставление Дельфи ран-тайма не-дельфи инструменту, не является какой-то уникальной мыслью. Например, инструмент, написанный Алексеем Волковым - Script Builder. Он и будет иллюстрацией того, что я имею в виду под Delphi Run-Time. Script Builder - это Delphi Run-Time для Microsoft Active Scripting (VBScript, JavaScript, ActivePerl, ActivePython). Скачать его можно с: http://www.volkoff.ru/file_download/4/sbpro.exe Script Builder написан на Delphi5 довольно давно (2000-й год) и имеет немного старомодный интерфейс. Но если вы его скачаете и немного "пощупаете", то увидите, что это продукт более качественный, чем те же Xailer или тем более Visual xHarbour. А по уровню предоставляемого ран-тайма и его расширяемости и сравнивать нечего, это, собственно, дельфи. Так вот, под "Delphi Run-Time for [x]Harbour" я подразумеваю аналогичный (но более современный инструмент) для [x]Harbour, который полностью поддерживал бы Unicode (имею в виду визуальные компоненты). ----- Реализация. Ясно, что начинать надо с 2-x сторон. 1) Delphi-часть, сначала собственно ран-тайм, здесь в общем-то все понятно и я могу это реализовать. 2) [x]Harbour-часть, здесь необходима некоторая библиотека, которая бы обеспечивала прозрачный доступ к классам, объектам Дельфи и делала бы их частью своего языка. Здесь моих знаний [x]Harbour явно не хватит. То есть, одному мне такой проект не поднять... Поэтому и пишу Паша, Григорий, Петр и другие уважаемые форумчане! Что вы думаете об этом? О возможном своем участии? Жду ваши комменты Спирин Сергей.

Ответов - 121, стр: 1 2 3 4 5 6 7 All

Петр: Мысли имеют право на жизнь В Harbour до сих пор не реализована поддержка Unicode, OOP тоже фактически можно считать не реализованным полностью. После выпуска версии 2.0 (надеюсь до конца этого года) в развитии продукта будет пауза, связанная с введением HB_<TYPE>. Т.е. Harbour, равно как и любой другой более менее большой мультиплатформенный С/С++ проект, будет переписан с использованием "своих" базовых типов (HB_BOOL, HB_BYTE, HB_CHAR и т.д. ), а не стандартных. Как предполагают разработчики при этом возникнут неизбежные ошибки, которые сделают невозможным использование кода с SVN на месяцы, а то и год (ы). В это время, возможно, и будет переписана VM для полноценной поддержки Unicode, изменено API (если кто-то заметил в API в последние месяцы внесено довольно много новых фукций, некоторые помечены как deprecate), изменена версия PCODE, потеряна совместимость с предидущими версиями как на бинарном, так и, частично, на уровне исходников (С code). О планах изменений в xHb не читал, но, думаю, там дела с реализацией изложенного обстоят немного хуже и некоторые вещи вообще не планируются (может и ошибаюсь ). Все это придется учитывать при организации Delphi Run-Time для [x]Harbour. Я думаю - эта работа посложнее FastReport for [x]Harbour и будет требовать не мало времени/сил, нестандартных решений. Если продукт на выходе будет иметь тоже качество, что и Xailer ( о Visual xHarbour помолчу) - лучше не начинать. И так многое не в его пользу - на слабых, старых машинах/ОС я так понял его использовать нельзя будет, dll/bpl куча будет не меньше чем в Alaska xBase++ (у многих клипперщиков какое-то необъяснимое предубеждение против dll), использовать можно будет только для написания новых проектов. Теперь о возможном участии. Почему бы и нет? P.S. Почитал о возможностях Delphi 2010 Enterprise - Подключение к серверам баз данных InterBase, Firebird, Blackfish SQL, MySQL, Microsoft SQL Server, Oracle, DB2, Informix и Sybase - на это у пользователей [x]harbour все чаще возникает спрос.

PSP: Петр пишет: при этом возникнут неизбежные ошибки, которые сделают невозможным использование кода с SVN на месяцы, а то и год (ы) Можно Вас попросить, Петр, сообщить нам об этом заранее? :)

Sergey Spirin: Петр пишет: Мысли имеют право на жизнь Петр пишет: Теперь о возможном участии. Почему бы и нет? Отлично Что ж, тогда можно начинать разговор более конкретный Наверное, самое первое - проект будет коммерческим? Делать здесь OpenSource думаю смысла нет. Дельфи то покупать придется Петр пишет: Если продукт на выходе будет иметь тоже качество, что и Xailer ( о Visual xHarbour помолчу) - лучше не начинать. И так многое не в его пользу - на слабых, старых машинах/ОС я так понял его использовать нельзя будет, dll/bpl куча будет не меньше чем в Alaska xBase++ (у многих клипперщиков какое-то необъяснимое предубеждение против dll), использовать можно будет только для написания новых проектов. Ну как он может иметь тоже качество, что и Xailer? Ведь основная цель проекта - портирование функционала Дельфи. А Дельфи и Xailer - даже и сравнить странно То есть, если в итоге получится Xailer, то дело явно будет в "кривых ручках" исполнителей Про старые машины. Быстродействие дельфийского кода намного выше того, что я когда-либо видел для Xbase. Поэтому, здесь, явно заблуждение. Если мы выберем Delphi2010 с полным Unicode, то мы просто отрежем Win95/98, но чисто технологически отрежем, быстродействие здесь не при чем. Код будет работать хоть на Pentium1. Размеры ран-тайма: В Аляске счас глянул - 20 dll общим размером ~8 mb. Что будет в Delphi run-time? Смотрю Delphi7, 2010 у меня еще нет: rtl70.bpl - 780 KB vcl70.bpl - 1.3 MB vcldb70.bpl - 270 KB Harbour70.bpl - 150 KB + какие-то библиотеки, используемые пользователем Этот набор уже больше чем тот же Xailer по функционалу... В 2010 размер будет побольше, но мне кажется вполне нормальным. Ничего страшного в этом нет, а возможности совсем иные. Петр пишет: Я думаю - эта работа посложнее FastReport for [x]Harbour и будет требовать не мало времени/сил, нестандартных решений. А по Delphi-части я, кстати, так не думаю. Самый сложный класс - THarbourDataSet, который делает Harbour-источники данных родными для Дельфи, написан именно в рамках FRH . Но по Harbour-части, думаю да. У вас, кстати, есть мысли по реализации Harbour-части? То есть, нам нужно реализовать некоторые "оболочки" над Дельфи-классами. Чтобы спокойно компилился типа такого код: Form1 := TForm.Create(nil) Grid1 := TDBGid.Create(Form1) Grid1:Parent := Form1 В результате выполнения такого кода должна "дергаться" моя dll-ка: CreateObject('TForm', nil) CreateObject('TDBGrid', pointer to Form1) SetProperty(pointer to Grid, 'Parent', pointer to Form1) Собственно, если даже только такое реализуем, то получим ... FiveWin, но только более высокого качества Жду комментов


Петр: Sergey Spirin пишет: Наверное, самое первое - проект будет коммерческим? Решать вам, но думаю, что да, а иначе какой смысл Delphi покупать Быстродействие дельфийского кода намного выше того, что я когда-либо видел для Xbase. Поэтому, здесь, явно заблуждение. Никакого заблуждения нет, никто не сравнивает скорость исполнения машинного и pcode. Я в том смысле, что у Delphi 2010 требования XP (или 2000?) , многие разработчики Harbour работают еще с 95/98/NT 4. То есть, нам нужно реализовать некоторые "оболочки" над Дельфи-классами. Естественно было бы написать Harbour-классы обертки. Что-то вроде [pre2] #include "hbclass.ch" PROCEDURE main LOCAL Form1, Grid1 Form1 := TForm():Create() IF hb_isObject( Form1 ) ? __objDerivedFrom( Form1, "TForm" ) ENDIF Grid1 := TDBGrid():Create( Form1 ) IF hb_isObject( Grid1 ) ? __objDerivedFrom( Grid1, "TDBGrid" ) ENDIF //Grid1:SetParent( Form1 ) ? hb_isObject( Grid1:GetParent()) /** */ CLASS TForm PROTECTED: VAR pRealObject INIT Nil EXPORTED: METHOD Create( oOwner ) CONSTRUCTOR DESTRUCTOR Destroy ENDCLASS METHOD Create( ... ) CLASS TForm ::pRealObject := CreateRealObject( "TForm", ... ) ? "TForm created" RETURN Self PROCEDURE Destroy() CLASS TFORM DestroyRealObject( ::pRealObject ) RETURN /** CLASS TDBGrid */ CLASS TDBGRID PROTECTED: VAR pRealObject INIT Nil VAR Parent INIT Nil EXPORTED: METHOD Create( oOwner ) CONSTRUCTOR METHOD SetParent( oOwner ) METHOD GetParent( oOwner ) DESTRUCTOR Destroy ENDCLASS // METHOD Create( oOwner ) CLASS TDBGRID IF hb_IsObject( oOwner ) .AND. __objDerivedFrom( oOwner, "TForm" ) ::pRealObject := CreateRealObject( "TDBGrid", oOwner ) ::Parent := oOwner ? "TDBGrid created" ELSE // ... ENDIF RETURN Self // METHOD SetParent( oOwner ) CLASS TDBGRID IF hb_IsObject( oOwner ) .AND. __objDerivedFrom( oOwner, "TForm" ) ::Parent := oOwner ELSE // ... ENDIF RETURN ::Parent // Self ? // METHOD GetParent( ) CLASS TDBGRID RETURN ::Parent PROCEDURE Destroy() CLASS TDBGRID DestroyRealObject( ::pRealObject ) RETURN /** stub */ FUNCTION CreateRealObject( ... ) RETURN // FUNCTION DestroyRealObject( ... ) RETURN /** typedef void* (__stdcall *CreateObject ) ( char*, void* ); static HMODULE hDll; HB_FUNC( CREATEREALOBJECT ) { // HMODULE hdll = LoadLibrary( "DelphiRT.dll" ); if( hdll ) { CreateObject f = (CreateObject) GetProcAddress( hDll, "CreateDelphiObject" ); if( !f ) { //.. } else { void* r = f( hb_parc(1), hb_parptr( 2 ) ); hb_retptr( r ); } // FreeLibrary( hdll ); } else { //.. } } */[/pre2]

Andrey: Петр пишет: Sergey Spirin пишет: цитата: Наверное, самое первое - проект будет коммерческим? Решать вам, но думаю, что да, а иначе какой смысл Delphi покупать Сделайте сначала НЕ коммерческий ! Для Turbo-Delphi ! Не у всех же есть возможность купить коммерческую лицензию Delphi .... А для желающих и с большими возможностями ВСЕ остальное....

Sergey Spirin: Andrey пишет: Сделайте сначала НЕ коммерческий ! Для Turbo-Delphi ! Не у всех же есть возможность купить коммерческую лицензию Delphi .... Андрей, Delphi покупать нужно будет нам, чтобы такую либу компилировать. А не конечным пользователям. Петр пишет: Я в том смысле, что у Delphi 2010 требования XP (или 2000?) , многие разработчики Harbour работают еще с 95/98/NT 4. Ну, пользователям Delphi то сам и не нужен. IDE Delphi действительно стало тяжеловатым после того как его сделали универсальным для всех языков - С++, C.Net, Delphi.Net (с 2005-го). То есть, часть этого IDE написана на .NET, требует NET Framework и т.д. Но сам производимый код компилятором Delphi так и остается - native Win32, поэтому будет работать на любой Win32 - машине. Петр пишет: Естественно было бы написать Harbour-классы обертки. Что-то вроде ...При таком подходе получается, что нам надо "задублировать" объявления всех (!) классов. Это.. долго будет Нельзя ли как-то поуниверсальней что-то придумать....?

Dima: Sergey Spirin пишет: Delphi покупать нужно будет нам Бери да пользуйся ;) http://torrents.ru/forum/viewtopic.php?t=2147307

Петр: Sergey Spirin пишет: При таком подходе получается, что нам надо "задублировать" объявления всех (!) классов. Это.. долго будет А их, что - много ? Можно написать на Delphi генератор шаблонов. Я в сети видел пример как с помощью RTTI перечисляются методы и свойства TButton. А CREATE CLASS в текстовый файл вывести не составит труда

Sergey Spirin: Dima пишет: Бери да пользуйся ;) http://torrents.ru/forum/viewtopic.php?t=2147307 Ох Круто было бы еще и умудриться продавать то, что компилируется на украденном Дим, я этого очень не люблю.. Конечно, посмотреть можно, но работать на краденном ???? Петр пишет: А их, что - много ? Да не мало будет Конечно, сотни, если не тысячи. Петр пишет: Можно написать на Delphi генератор шаблонов. Я в сети видел пример как с помощью RTTI перечисляются методы и свойства TButton. Это, конечно, можно.... Единственное, счас пока не соображу, как автоматом обойти все классы.... То есть не просто по вертикали, а захватывать все горизонтали Но "результирующая" текстовая портянка - это будет нечто Что-то мне хочется какого-то другого пути... ??? P.S. Пожалуй в ближайшие дни займусь установкой Delphi2010. Все, что я сейчас о ней читаю, убеждает в мысли, что если делать, то делать именно на ней... Будет намного проще.

Dima: Sergey Spirin пишет: Конечно, посмотреть можно Так для этого и дал ссылку , чисто для ознакомления

Sergey Spirin: Dima пишет: Что-то мне хочется какого-то другого пути.. Я как-то смутно припоминаю, что например в MiniGui объeкты/методы разделяются точкой, а не двоеточием. Более того, вроде этих самых объектов там нет вовсе... То есть, производится некоторое "перенапрвление" синтаксиса? Каким образом это достигается? Нельзя ли "зацепиться" каким-то подобным образом? Используя синтаксис... как текстовый параметр для dll?

Петр: Sergey Spirin пишет: Каким образом это достигается? Используя препроцессор. #translate System.Clipboard => RetriveTextFromClipboard() #translate System.Clipboard := <arg> => CopyToClipboard ( <arg> ) #translate System.DesktopWidth => GetDesktopWidth() #translate System.DesktopHeight => GetDesktopHeight() #translate System.DefaultPrinter => GetDefaultPrinter() Т.е. все эти псевдообьекты известны не то что-бы во время исполнения, а до того. Короче - раннее связывание Нельзя ли "зацепиться" каким-то подобным образом? Подобным нет, но вообще - можно. Есть такой трюк для "продвинутых" - Object over Hash и ON ERROR метод.

Sergey Spirin: Петр пишет: Object over Hash и ON ERROR метод. А это что такое? ON ERROR? Это все время падать в обработчик ошибки и такм "разруливать"?

Петр: Sergey Spirin пишет: Это все время падать в обработчик ошибки и такм "разруливать"? Именно так. Ладно, завтра постараюсь сделать несколько примеров - на выбор может что и понравится, с другой стороны хотелось бы знать конкретнее, что могут возвращать методы SetProperty, GetProperty

Петр: Sergey Spirin пишет: ON ERROR? Это все время падать в обработчик ошибки и такм "разруливать"? Этот код был впервые опубликован by Mindaugas Kavaliauskas. Хотя как говорится - идея витала в водухе И многие использовали ERROR HANDLER по своему усмотрению. Ясно, что здесь нет всех необходимых проверок и конечно это всего лишь пример, но в качестве "пищи для ума" - сойдет [pre2]#include "hbclass.ch" PROC MAIN() LOCAL hValue := HashObject() hValue:VAR1 := 123.45 hValue:VAR2 := DATE() ? hValue:VAR1, hValue:VAR2 // Let's create method for HashObject() hValue:PrintVar1 := @HO_PrintVar1() hValue:PrintVar1( 10000 ) RETURN STATIC PROC HO_PrintVar1( nOffset ) ? "I'm a function used as method" ? QSELF():VAR1 + nOffset RETURN CREATE CLASS HashObject VAR __hash INIT {=>} ERROR HANDLER OnError() ENDCLASS METHOD OnError( ... ) CLASS HashObject LOCAL cMessage := __GETMESSAGE(), xValue ? cMessage IF PCOUNT() == 1 .AND. LEFT( cMessage, 1 ) == "_" RETURN QSELF():__hash[ SUBSTR( cMessage, 2 ) ] := HB_PVALUE( 1 ) ENDIF xValue := QSELF():__hash[ cMessage ] IF HB_ISSYMBOL( xValue ) RETURN HB_EXECMSG( xValue, QSELF(), ... ) ENDIF RETURN xValue [/pre2] Осталось скрестить два мои примера и адаптировать к своим нуждам

Sergey Spirin: Петр пишет: Именно так. Ну это как-то уж чересчур, кажется... Петр пишет: хотелось бы знать конкретнее, что могут возвращать методы SetProperty, GetProperty Вообще, в RTTI для свойств определены следующие возможные варианты (не типы) : [pre]TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat, tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkWString, tkVariant, tkArray, tkRecord, tkInterface, tkInt64, tkDynArray); [/pre] В FRH я использую унифицированный тип доступа к свойствам через Variant. Variant - тип данный, который может быть чем угодно (почти): [pre]function GetPropValue(Instance: TObject; const PropName: string; PreferStrings: Boolean = True): Variant; procedure SetPropValue(Instance: TObject; const PropName: string; const Value: Variant); [/pre] В FRH я работаю через харборовские Item-ы. Думаю, что проще так и продолжать. То есть, GetProperty - будет возвращать указатель на Item, а SetProperty принимать его как параметр. В FRH я делаю преобразование ItemToVar и VarToItem, типа: [pre]function ItemToVar(PItem: Pointer): Variant; var ItemType, Len, x: ULong; AStr: string; tmpItem: Pointer; AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word; begin ItemType := hb_itemType(PItem); case ItemType of HB_IT_NIL : Result := Null; HB_IT_POINTER : Result := Integer(hb_itemGetPtr(PItem)); HB_IT_INTEGER : Result := hb_itemGetNI(PItem); HB_IT_LONG : Result := hb_itemGetNL(PItem); HB_IT_DOUBLE : Result := hb_itemGetND(PItem); HB_IT_DATE : begin AStr := StringOfChar(' ', 8); hb_itemGetDS(PItem, PChar(AStr)); if AStr = StringOfChar(' ', 8) then Result := Null else Result := EncodeDate(StrToInt(Copy (AStr, 1, 4)), StrToInt(Copy(AStr, 5, 2)), StrToInt(Copy(AStr, 7, 2))); end; HB_IT_TIMEFLAG, ........................................ function VarToItem(V: variant; PItem: Pointer = nil): Pointer; var AInt, Diff, x: LongInt; ADouble: Double; AStr: string; ABOOL: BOOL; TmpItem: Pointer; function GetXppDateStr(const ADate: TDateTime): String; var Y, M, D: Word; begin DecodeDate(ADate, Y, M, D); Result := Format('%4d%2d%2d', [Y,M,D]); Result := StringReplace(Result, ' ', '0', [rfReplaceAll]); end; begin case VarType(V) of varEmpty, varNull: begin if Assigned(PItem) then begin hb_itemClear(PItem); Result := PItem; end else Result := hb_itemNew(nil); end; varInteger: begin AInt := V; Result := hb_itemPutNL(PItem, AInt) end; varSingle, varDouble, varCurrency: begin ADouble := V; Result := hb_itemPutND(PItem, ADouble); end; varDate: begin if (StateOfDATETIME = 0) or (Frac(V) = 0) then begin AStr := GetXppDateStr(V); Result := hb_itemPutDS(PItem, PChar(AStr)); end else begin ...................... [/pre] Из этих фрагментов, я думаю, смысл манипулирования понятен. Дополнительного продумывания я думаю потребуют очень популярные для свойств перечислимые типы и множества, например в Delphi: type TBorderIcon = (biSystemMenu, biMinimize, biMaximize, biHelp); TBorderIcons = set of TBorderIcon; property BorderIcons: TBorderIcons read FBorderIcons write SetBorderIcons stored IsForm default [biSystemMenu, biMinimize, biMaximize]; Может быть, только работы через Variant и не хватит, придется дополнять. Но в целом, работа со свойствами это самый непроблемный кусок

Петр: Sergey Spirin пишет: Ну это как-то уж чересчур, кажется... Да нормально - это еще не извращения И по скорости исполнения - вполне сносно, если на OnError на С переписать В FRH я работаю через харборовские Item-ы. Ясно type TBorderIcon = (biSystemMenu, biMinimize, biMaximize, biHelp); TBorderIcons = set of TBorderIcon; property BorderIcons: TBorderIcons read FBorderIcons write SetBorderIcons stored IsForm default [biSystemMenu, biMinimize, biMaximize]; Здесь не совсем ясно - но предполагаю что это в С что-то вроде битовых операций?

Sergey Spirin: Петр пишет: Осталось скрестить два мои примера и адаптировать к своим нуждам Пока, что может получиться из такого скрещивания, для меня не очень понятно Вообще же, можно сформулировать что нам нужно так: - Переменная, которая использовалась для создания Delphi-объекта должна хранить указатель на него. - Этот указатель используется в дальнейшем при обращении к свойствам и методам, деструктору. - И !!! Обработчики событий! ... Похоже переменная просто обязана все-таки быть объектом, иначе, что такое будет Button1Click(Sender) ? Все-таки должно быть ведь что-то типа: CLASS TForm1 FROM TForm EXPORTED: METHOD Button1Click(oSender) ENDCLASS - Именно такое должен увидеть пользователь в будущем Дизайн-Тайме в файле при создании обработчика. - Ну и последующая задача Save/Load dfm(дельфи форм) в ресурсах exe. В ран-тайме при загрузке - восстановление всех обработчиков.

Sergey Spirin: Петр пишет: Здесь не совсем ясно - но предполагаю что это в С что-то вроде битовых операций? Да. Точно. Это просто удобная паскалевская обертка. Просто надо будет подумать как обернуть, но думаю это не сложно, в С++ Builder-е например это же сделано

Петр: Sergey Spirin пишет: Переменная, которая использовалась для создания Delphi-объекта должна хранить указатель на него. Пример №1 - VAR pRealObject Этот указатель используется в дальнейшем при обращении к свойствам и методам, деструктору. Естественно - пример №1 CLASS TForm1 FROM TForm EXPORTED: METHOD Button1Click(oSender) ENDCLASS Все таки - нужно писать классы обертки? Переопределять хотя бы основные методы. Остальное можно через OnError



полная версия страницы