Harbour — новое лицо xBase family

от автора

Для справки: xBase — семейство систем программирования, СУБД, берущих начало с dBase (1980 г.). Их объединяет общий язык программирования ( естественно, с вариациями, присущими конкретной реализации ) и встроенные в этот язык средства доступа к реляционным базам данных формата DBF. Собственно, dBase начинался как СУБД с языком, предназначеннным для обслуживания баз данных. Это процедурный язык программирования, он относится к группе интерпретируемых языков и обладает многими, если не всеми, их родовыми чертами, такими, например, как динамическая типизация.

Clipper, непосредственный предшественник Harbour, был создан в 1985 г. с целью повышения производительности dBase III. Для этого исходный код программы преобразовывался на стадии компиляции в байт-код, который встраивался в исполнямый файл вместе с виртуальной машиной, предназначенной для исполнения этого байт-кода. Таким образом, Clipper давал на выходе автономный exe файл, не требующий для своего запуска и выполнения внешнего интерпретатора, как в случае dBase или FoxBase ( другой популярный xBase продукт ).

В конце 80-х и начале 90-х Clipper был очень популярен, он был одним из основных средств программирования для приложений, связанных с использованием баз данных, в первую очередь бухгалтерских, управленческих, банковских. Язык модернизировался от версии к версии, добавлялись новые подсистемы. Среди последних особенно следует отметить Extend System и RDD. Extend System (система расширения) предназначена для связи с модулями, написанными на С — вызов функций, передача параметров, получение возвращаемых значений. RDD — Replaceable Database Drivers (заменяемые драйверы баз данных) — технология, которая позволяла, прилинковав взамен стандартной другую, специальную библиотеку, работать с БД другого типа, не изменив ни строчки кода. Именно так Clipper-приложения работали, например, с Novell’овским Btrieve (если кто помнит, была такая клиент-серверная не SQL СУБД).

XBase системы всегда воспринимались как предназначенные, в первую очередь, для работы с базами данных и, возможно поэтому, с ростом популярности SQL стали выходить из тренда. И если с Fox’ом все было более-менее благополучно — купившая его Microsoft сделала на его основе популярный продукт Visual Foxpro, который еще несколько лет назад (в 2006, согласно Википедии), был на почетном 12-м месте в списке TIOBE, то у Clipper дела были куда хуже. Computer Associates, которая владела им с начала 90-х, сделала ставку на другие продукты. Clipper же остался в стороне от магистрального пути, назревшие проблемы не решались, а в 1997 году Computer Associates объявила о закрытии дальнейшей его разработки, оставив пишущих на нем программистов наедине с 16-разрядной, рассчитанной на применение в среде MS-DOS системой программирования.

Многие из тех, кто задумывался о своем будущем, мигрировали на другие платформы, но остались и те, кто считал, что достоинства Clipper, будучи реализованы в современной среде программирования, будут востребованы и дальше. Были созданы несколько таких реализаций (xBase++, Clip, Harbour), об одной из которых, наиболее успешной на этот день я и поведу речь — прошу простить меня за такое длинное, но, на мой взгляд, необходимое вступление.

Итак, Harbour. Проект стартовал в 1999 году, официальный сайт — www.harbour-project.org. Текущая версия — 3.0 (stable), 3.2 (development).

Как и Clipper, Harbour транслирует исходный текст программы в байт-код, но, в отличие от своего предшественника, компилятор Harbour создает не объектные, а с файлы, которые потом надо «скормить» С компилятору. Например, вот такую простейшую функцию, выводящую приветствие на консоль:

Function Hello    ? "Hello"    Return Nil 

он транслирует в (комментарии — мои):

// HB_FUNC определено как: // #define HB_FUNC( funcname )        HB_EXTERN_C_ HB_EXPORT HARBOUR HB_FUN_##funcname ( void )  HB_FUNC( HELLO ) {    // байт-код    static const HB_BYTE pcode[] =    {       36,2,0,176,2,0,106,6,72,101,108,108,111,0,       20,1,36,3,0,100,110,7    };    // Вызов виртуальной машины (далее - ВМ) для выполнения байт-кода    hb_vmExecute( pcode, symbols ); } 

Рассмотрим байт-код подробнее:

   static const HB_BYTE pcode[] =    {       36,2,0,                          // 36 - код, за которым следует номер строки                                         // исходного текста, в данном случае - 2       176,2,0,                         // 176 - помещает символ на стек ВМ, имеется                                         // ввиду символ, представляющий функцию вывода       106,6,'H','e','l','l','o','\0',  // 106 - помещает строку на стек ВМ       20,1,                            // 20 - ВМ должна выполнить функцию и отбросить                                         // ее результат, 1 - количество параметров       36,3,0,                          // 36 - код, за которым следует номер строки                                         // исходного текста, в данном случае - 3       100,                             // 100 - помещает Nil на стек ВМ       110,                             // 110 - ВМ должна вернуть значение с вершины стека       7                                // 7 - ВМ должна завершить работу    }; 

Ваш проект может включать исходники на Harbour (*.prg), на C, специальные объектные файлы и библиотеки. С код может быть встроен и в prg-файл, его надо заключить в #pragma BEGINDUMP#pragma ENDDUMP и, естественно, он должен соответствовать соглашениям EXTEND SYSTEM (я упоминал о ней, когда говорил о Clipper). Ниже — пример такого симбиоза:

Function Main    ? Sinus( 30 ), Sinus( 60 )    ?     Return Nil  #pragma BEGINDUMP #include <math.h> #include "hbapi.h" #include "hbapiitm.h"  #define PI 3.14159265 // Вычисляем синус угла, заданного в градусах  HB_FUNC( SINUS ) {    // hb_parnd( n ) - функция EXTEND SYSTEM, принимает n-й переданный параметр    //    как double из Harbour функции    // hb_retnd( d ) - функция EXTEND SYSTEM, возвращает double значение d    //    обратно в Harbour функцию     hb_retnd( sin( hb_parnd( 1 ) * PI / 180 ) ); } #pragma ENDDUMP 

Я не случайно уделил столько внимания С в Harbour. Расширенная ( извините за невольную тавтологию ), по сравнению с Clipper, Extend System и Item API, предоставляющая доступ из С кода к внутренним структурам Harbour, его переменным, массивам, объектам позволяют говорить о симбиозе двух языков, я считаю это одной из важнейших особенностей Harbour. Благодаря этому Harbour уже «оброс» большим количеством модулей — оболочек к разнообразным продуктам, имеющим C API и список таких модулей, как open source, так и коммерческих, постоянно растет (в настоящее время подумываю об OpenCV). Конечно же, С используется в Harbour не только для создания оболочек к готовым продуктам, но и для самостоятельных разработок — новые RDD, GUI библиотеки и др. Иногда, в контексте некоторых приложений я рассматриваю Harbour как оболочку к С коду — для облегчения реализации пользовательского интерфейса, доступа к БД и пр.

Встроенный доступ к БД, эта родовая черта xBase, — еще одна тема, которой хочется уделить особое внимание. Это, действительно, очень удобно — иметь возможность, не используя внешние СУБД, с помощью только встроенных языковых средств производить все необходимые манипуляции с базами данных — создание, модификация, пополнение, редактирование, поиск. В случае, когда количество информации, хранящейся в БД, сравнительно невелико, использовать внешнюю СУБД представляется совершенно излишним, для таких приложений и MySQL выглядит монстром (а ведь некоторые даже MS SQL ставят) — xBase подход здесь выглядит наиболее адекватным решением. Впрочем, и для больших БД Harbour может применяться (и применяется) вполне успешно.

Приведу небольшой фрагмент кода, демонстрирующий типичные конструкции доступа к данным — для тех, кто не сталкивался с xBase языками раньше. Конечно же, арсенал средств для работы с БД в Harbour гораздо богаче, чем использованный в этих нескольких строчках.

Function Test    Local aStru := { {"FAMILY","C",16,0}, {"IMYA","C",16,0}, {"OTCHES","C",16,0}, ;       {"TELEFON","C",10,0} }     // Создаем таблицу БД mytable с ФИО и номерами телефона    dbCreate( "mytable", aStru )     // Открываем mytable    USE mytable     // Создаем индексы по фамилии и по телефону    INDEX ON FAMILY TAG FAMILY    INDEX ON TELEFON TAG TELEFON     // Добавляем записи    APPEND BLANK    REPLACE FAMILY WITH "Иванов", IMYA WITH "Игорь", OTCHES WITH "Константинович", ;       TELEFON WITH "9101682020"    ...     // Ищем запись по номеру телефона, используя индекс    ordSetFocus( "TELEFON" )    IF dbSeek( "9101682020" )       // Если запись найдена, изменяем номер       REPLACE TELEFON WITH "9102875555"    ENDIF    ...     Return Nil 

Средства доступа к БД не ограничиваются стандартными. Есть RDD, написанные для клиент-серверных СУБД, как основанных на DBF ( коммерческая Advantage Database Server от Sybase и open source LetoDb ), та и SQL. Есть модули, обеспечивающие доступ посредством ODBC и ADO, есть модули для MySQL, PostgreSQL, SQLite, использующие C API этих СУБД.

В Harbour получили дальнейшее развитие все особенности Clipper, сделавшие его языком высокого уровня, на котором удобно программировать — автоматическое выделение и освобождение памяти, сборщик мусора, так называемые raw arrays, возможность компилировать и исполнять в run-time, в динамике фрагменты кода. Добавлена полноценная реализация ООП. Препроцессор, сохранив всю мощь Clipper’овского, расширен за счет некоторых конструкций, взятых из С. Впрочем, не буду перечислять здесь все новшества, а просто сошлюсь на раздел моего сайта Harbour для начинающих.

Да, я, кажется, забыл сказать, что Harbour — кроссплатформенная система с открытыми исходниками. Он существует на 32- и 64-разрядных платформах, на Windows, Linux, Unix, Mac OS X, QNX, OS/2, вроде бы и на Android, и еще на чем-то, чего я не видел.

Буду рад, если эта статья вызовет интерес. В этом случае можно будет рассмотреть какие-то аспекты более подробно.

ссылка на оригинал статьи http://habrahabr.ru/post/198618/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *