Harbour для начинающих
Описывается «курс молодого бойца» для освоения языка программирования Harbour — современной «реинкарнации» семейства xBase-языков, предназначенных, в основном, для манипуляции данными, содержащимися в реляционных базах данных (примеры подобных языков — dBase, Clipper, Foxpro).
Основной материал — с сайта Александра Кресина.
(за основу «Содержания» взял — пока — структуру из английского учебника Application Development with Harbour — А. Густов)
Введение
[править]Установка
[править]Скачиваем Harbour
[править]Официальные дистрибутивы Харбора находятся на Sourceforge. Там выложены как исходники, так и готовые к работе бинарные пакеты. Если вам нужен бинарник, то выбираете предназначенный для вашей платформы (Windows, какой-либо из Юниксов/Линуксов, OS/2 и пр.). Может оказаться, что такого нет, или что для вашей платформы отсутствует последняя версия — это часто бывает, так как разных Юниксов/Линуксов много, а число активных разработчиков — тех кто готов компилировать, тестировать и выкладывать пакеты на разных платформах — ограничено. Так вот, если не найдете свой пакет, не расстраивайтесь — путь к Харбору для вас не закрыт. Скачивайте исходники и собирайте из них готовый к работе бинарный пакет. Это совсем не сложно, гораздо проще, чем может показаться сначала. Кстати, если для нужной вам платформы отсутствует бинарный пакет последней версии, может быть, имеет смысл скачать ту версию, которая есть. И 2.0, и даже 1.0 вполне хороши и, возможно, будут полностью удовлетворять вашим потребностям.
Если вы решили скачать исходники, то на соответствующей странице (вот прямая ссылка) вы найдете ссылки на исходники разных версий и на так называемый nightly (ночной) — это слепок, снимок исходников, взятый из репозитария разработчиков прошедшей ночью. Есть еще один способ достать исходники — непосредственно из репозитария разработчиков с помощью SVN-клиента. Лично я не вижу в этом большого смысла, разве только вы решите присоединиться к разработчикам или для вас критически важен код, выложенный пять минут назад… Если так, то почитайте следующий подраздел — про SVN.
Что такое SVN
[править]SVN, или Subversion (см. статью в Википедии) — это система управления версиями, заменившая CVS. Итак, CVS — это программа с серверной и клиентской частями, которая позволяет разработчикам, у которых установлены клиентские части, совместно работать с исходниками проекта, которые находятся на сервере (в Интернет или в локальной сети), разрешает конфликты, возникающие при одновременном изменении одного файла разными людьми. При этом CVS обеспечивает и контроль версий — то есть, все версии каждого файла хранятся, могут быть извлечены, восстановлены; можно проверить, кем и какие изменения были сделаны. Очень удобная штука, рекомендую ее, или ее предшественника CVS, и для внутреннего использования в организации.
Харбор «живет» на SourceForge.net — крупнейшем портале для Open Source проектов. Установив SVN клиент, вы можете получить доступ к исходникам Харбора — самому последнему варианту, как у разработчиков. В первый раз вам придется скачать полный набор (~16M), при последующих обращениях передаваться будут только изменения.
SVN можно скачать с сайта этого продукта. Если у вас Линукс, то, возможно, клиент SVN входит в состав вашего дистрибутива. Если у вас Windows, вы можете скачать с моего сайта svn_mini.zip — здесь только то, что необходимо плюс bat файл для запуска SVN клиента. Создаете у себя каталог, например, SVN, распаковываете туда svn_mini.zip и запускаете svn_hrb_upd.bat.
А вот и строчка для получения исходников из Harbour-репозитария:
svn co https://harbour-project.svn.sourceforge.net/svnroot/harbour-project/trunk/harbour
Выбираем C компилятор
[править]Есть один важный вопрос, который вам надо решить для себя сразу, до скачивания дистрибутива Харбора — это вопрос о С компиляторе.
Дело в том, что сам компилятор Харбор не создает объектные файлы (obj, o), результатом его работы является *.c файл, который надо затем скомпилировать С компилятором, чтобы получить исполняемый файл (exe’шник — для Windows). Но пусть это вас не пугает! Вам не обязательно знать для этого С — достаточно, чтобы С компилятор был у вас установлен. А использование его для компиляции и линковки ваших файлов ничуть не сложнее, чем использование Rtlink или Blinker’а.
Если вы работаете в Линуксе, или в любом из Unix’ов, в MAC OS, OS/2, то C компилятор у вас уже есть — это стандартный GNU C. если же ваша платформа — Windows, то надо выбирать. Многие из тех, кто работает с Харбором, используют бесплатный Borland C 5.5.1, его можно скачать с этой странички. Другой популярный C компилятор — Mingw (http://www.mingw.org). Если у вас уже стоит C++ Builder или Visual C, можете использовать их. Бинарный дистрибутив Harbour под Windows, предоставляемый в виде установочного exe файла, включает в себя Mingw C компилятор.
Примечание для тех, кто будет устанавливать Borland C 5.5.1 и не прочитает их readme.txt:
чтобы он работал, необходимо вручную создать в bcc55\bin 2 файла:
BCC32.CFG:
-I"c:\Borland\Bcc55\include" -L"c:\Borland\Bcc55\lib"
и ILINK32.CFG:
-L"c:\Borland\Bcc55\lib;c:\Borland\Bcc55\lib\PSDK"
Кстати, чтобы запустить на исполнение небольшую программу, вы можете обойтись и без С. (когда сделаете соотв. раздел — у Кресина метка «#Compile6» — поставьте внутреннюю ссылку на него на словах «без C»!)
Устанавливаем бинарники Harbour
[править]Бинарные пакеты распространяются в форматах, специфичных для соответствующей платформы. Для Windows это exe’шник — запускаете его и следуете инструкциям установщика; для Ubuntu это deb файл — пользователи Ubuntu знают, что с ним делать; ну и т. д.
Устанавливаем Harbour из исходников
[править]Чтобы построить Харбор — компилятор и библиотеки, нам необходимо иметь C компилятор, об этом мы уже говорили ранее.
В корне вашего дистрибутива Harbour есть файл README.txt (до 14.11.2012 он назывался INSTALL), там содержатся подробные инструкции по сборке Харбора из исходников. Правда, этот файл — на английском языке. Ниже я расскажу об этом очень кратко, для большинства случаев этого будет достаточно.
Если у вас Windows, укажите путь к каталогу bin вашего C компилятора и запускайте win-make.exe — этот файл есть в вашем дистрибутиве Harbour. Я обычно делаю bat’ник с этими строками и запускаю его на исполнение.
Так, если у вас Borland C 5.5, то это будет выглядеть примерно так:
set path=c:\borland\bcc55\bin win-make.exe
Для mingw может быть вот так:
set path=c:\mingw\bin win-make.exe
Для Open Watcom:
set watcom=C:\watcom set path=%WATCOM%\BINNT;%WATCOM%\BINW;%PATH% set edpath=%WATCOM%\EDDAT set include=%WATCOM%\H;%WATCOM%\H\NT win-make.exe
Если у вас Линукс/Юникс, то достаточно запустить команду make.
Примеры для других платформ и компиляторов смотрите в README.txt (до 14.11.2012 он назывался INSTALL), раздел 8.EXAMPLES, там их множество.
Для начала этого хватит, но впоследствии вам, возможно, потребуется установить дополнительные переменные окружения для управления процессом сборки. Полный их список смотрите, опять-таки, в README.txt, а здесь я приведу лишь несколько примеров, чтобы было ясно, о чем идет речь.
Некоторые модули Харбора (в основном, это дополнительные — те, что в contribs) зависят от так-называемых 3rd party компонентов, то есть от установленных у вас в системе сторонних программ. Например, для сборки библиотеки hbmysql из Harbour/contrib требуются файлы заголовков (.h) от MySql клиента, который у вас установлен. Поэтому, если вы хотите, чтобы эта библиотека была создана при сборке Харбора и чтобы она работала с установленным у вас MySQL клиентом, вы должны указать путь заголовкам этого клиента:
set HB_WITH_MYSQL=C:\mysql\include
Аналогично этому:
set HB_WITH_ADS=C:\ads\acesdk set HB_WITH_ALLEGRO=C:\allegro\include set HB_WITH_BLAT=C:\blat\full\source set HB_WITH_CAIRO=C:\cairo\include\cairo set HB_WITH_CURL=C:\curl\include set HB_WITH_GS=C:\ghostscript-9.01\psi set HB_WITH_GS_BIN=C:\ghostscript-9.01\bin (on Windows) set HB_WITH_FIREBIRD=C:\Firebird\include set HB_WITH_FREEIMAGE=C:\FreeImage\Dist set HB_WITH_GD=C:\gd\include set HB_WITH_OCILIB=C:\ocilib\include set HB_WITH_OPENSSL=C:\openssl\inc32 OR C:\openssl\include set HB_WITH_PGSQL=C:\pgsql\include
На Unix/Linux системах это обычно не требуется, так как все эти 3rd party компоненты расположены в строго определенных местах и программа сборки сама их найдет. Чтобы, наоборот, запретить сборку этих модулей, вам надо присвоить соответствующей переменной значение no.
Для некоторых из таких модулей все нужные файлы, и заголовочные в том числе, уже есть в составе Харбора. В этом случае вы можете или, как и выше, указать путь к установленному у вас компоненту, или присвоить переменной значение local — чтобы были использованы те самые Харборовские файлы и заголовки, или, наоборот, nolocal — чтобы запретить использование предопределенных в Харборе файлов:
set HB_WITH_BZIP2=C:\bzip2 set HB_WITH_EXPAT=C:\expat\lib set HB_WITH_JPEG=C:\jpeglib set HB_WITH_LIBHARU=C:\libharu\include set HB_WITH_LZF=C:\liblzf set HB_WITH_MINILZO=C:\minilzo\ set HB_WITH_MINIZIP=C:\zlib\contrib\minizip set HB_WITH_MXML=C:\minixml set HB_WITH_PCRE=C:\pcre set HB_WITH_PNG=C:\libpng set HB_WITH_SQLITE3=C:\sqlite3 set HB_WITH_TIFF=C:\libtiff set HB_WITH_TINYMT=C:\tinymt\tinymt set HB_WITH_XDIFF=C:\libxdiff-0.23\xdiff set HB_WITH_ZLIB=C:\zlib
Ну и, напоследок, еще одна переменная, она указывает на каталог, куда надо установить бинарники Harbour:
set HB_INSTALL_PREFIX
xHarbour
[править]xHarbour — это другой Harbour, ответвление (fork) от Harbour. В начале 2000-х один из разработчиков (Рон Пинкас) из-за разногласий с остальными членами команды покинул проект и основал свой. Впоследствии к нему присоединилась еще группа людей. Буква x в названии нового проекта должна была означать extended — «расширенный». Код был целиком унаследован от Harbour, но Пинкас внес в него свои изменения/дополнения, многие из которых были ранее отвергнуты основными разработчиками Harbour. По ходу дальнейшей разработки xHarbour заимствовал многое из Harbour и Harbour заимствовал кое-что из xHarbour, так что оба проекта тесно связаны и в большинстве случаев, если не использовать некоторые языковые расширения, программы успешно компилируются и тем, и другим. xHarbour существует в двух ипостасях :) — открытой и коммерческой. Чем они различаются — не знаю, разбирайтесь сами, если хотите. Подробно про различия между Harbour и xHarbour можно почитать в xhb-diff.txt — этот файл есть в любом дистрибутиве Harbour в каталоге Doc. Я с самого начала и до сих пор являюсь членом команды Harbour, использую исключительно его, что рекомендую и вам. Тем более, что на сегодняшний день (ноябрь 2012) Harbour надежнее, быстрее и богаче возможностями. Все, о чем здесь говорится, относится к Harbour. Многое (но не все — Hbmk, например в xHarbour не включена) из этого применимо и для xHarbour.
Компиляция и линковка программы
[править]Общие рассуждения
[править]Собрать свою программу в Harbour можно тремя способами: с помощью традиционной make-системы, которая входит в состав любого С компилятора, с помощью командных файлов (bat’ников — под Windows и shell скриптов под Unix/Linux) или используя специальную Harbour утилиту hbmk2. Здесь мы рассмотрим два последних способа.
Hbmk2, безусловно, удобная и мощная утилита. Главное ее достоинство в том, что она позволяет строить как простенькие программы, так и большие проекты, не вдаваясь в детали работы компилятора и линкера. Hbmk2 сама находит ваш С компилятор и производит необходимые действия. Что может быть проще, чем запустить из командной строки утилиту со списком исходных файлов проекта? Для более сложных случаев — если вам надо обязательно установить какие-то особые опции компиляции, присоединить дополнительные библиотеки, или использовать динамические библиотеки, — потребуется знать специальные параметры hbmk2, или даже создавать конфигурационные файлы проекта, но все равно это будет проще, чем использовать другие способы сборки.
Я, тем не менее, предпочитаю традиционный способ сборки — с помощью командных файлов, так как он дает полный контроль над процессом, с ним я четко вижу, что именно я делаю и зачем. Общая последовательность действий здесь простая:
1. Компилируем *.prg в *.c с помощью harbour.exe.
Параметры компилятора, в основном, те же, что и у Клиппера. Полный их список можно получить, запустив harbour.exe без параметров. В одной строчке можно указывать несколько prg файлов.
2. Компилируем *.с в объектные файлы вашим С компилятором.
3. Линкуем объектные файлы тем линкером, который поставляется с С компилятором.
При линковке надо обязательно указать список Харборовских библиотек, которые нужны вашему приложению.
Все используемые с Харбором С компиляторы позволяют объединить шаги 2 и 3 — делайте, как вам нравится.
Windows, bat файл
[править]Ниже приведен bat’ник, которым я обычно пользуюсь, чтобы скомпилировать один prg (Borland C, gtwin):
(для редакторов: тут надо как-то переформатировать, чтобы строчки с BCC32 не были столь длинными, то есть как-то организовать переносы)
@set HB_BIN_INSTALL=d:\harbour\bin @set HB_LIB_INSTALL=d:\harbour\lib @set HB_INC_INSTALL=d:\harbour\include\ %HB_BIN_INSTALL%\harbour %1.prg -n -i%HB_INC_INSTALL% bcc32 -O2 -d -I%HB_INC_INSTALL% -L%HB_LIB_INSTALL% %1.c hbdebug.lib hbvm.lib hbrtl.lib gtwin.lib hbcpage.lib hblang.lib hbrdd.lib hbmacro.lib hbpp.lib rddntx.lib rddcdx.lib rddfpt.lib hbsix.lib hbcommon.lib hbct.lib
Если вы хотите использовать gtwvt экранный драйвер, то последняя строчка будет выглядеть так:
bcc32 -O2 -tW -I%HB_INC_INSTALL% -L%HB_LIB_INSTALL% %1.c hbdebug.lib hbvm.lib hbrtl.lib gtwvt.lib hbcpage.lib hblang.lib hbrdd.lib hbmacro.lib hbpp.lib rddntx.lib rddcdx.lib rddfpt.lib hbsix.lib hbcommon.lib hbct.lib
Для Mingw C компилятора замените последнюю строчку на:
gcc -Wall -mno-cygwin -c -I%HB_INC_INSTALL% %1.c gcc -Wall -mwindows -o%1%.exe %1.o -L%HB_LIB_INSTALL%/win/mingw -Wl,--start-group -lhbvm -lhbrtl -lgtwvt -lhblang -lhbrdd -lhbmacro -lhbpp -lrddntx -lrddcdx -lrddfpt -lhbsix -lhbcommon -lhbcpage -lhbct -luser32 -lgdi32 -lwinspool -lcomctl32 -luuid -lkernel32 -lws2_32 -Wl,--end-group
Если вам надо построить программу из нескольких файлов, то можно использовать что-либо вроде этого (Borland C, gtwin):
@set HB_BIN_INSTALL=d:\harbour\bin @set HB_LIB_INSTALL=d:\harbour\lib @set HB_INC_INSTALL=d:\harbour\include\ %HB_BIN_INSTALL%\harbour file1.prg -n -i%HB_INC_INSTALL% %HB_BIN_INSTALL%\harbour file2.prg -n -i%HB_INC_INSTALL% ... bcc32 -O2 -d -I%HB_INC_INSTALL% -L%HB_LIB_INSTALL% file1.c file2.c ... hbdebug.lib hbvm.lib hbrtl.lib gtwin.lib hbcpage.lib hblang.lib hbrdd.lib hbmacro.lib hbpp.lib rddntx.lib rddcdx.lib rddfpt.lib hbsix.lib hbcommon.lib hbct.lib
Linux, sh скрипт
[править]Последовательность, естественно, та же, только синтаксис немножко другой (для консольного приложения с gtcrs):
#!/bin/sh HB_INS="/apps/harbour" $HB_INS/bin/harbour $1.prg -n -q0 -es2 -gc0 -I$HB_INS/include -I../include -d__LINUX__ gcc -I. -I$HB_INS/include -Wall -c $1.c -o$1.o gcc -Wall -o$1 $1.o -L $HB_INS/lib \ -Wl,--start-group -lhbvm -lhbrtl -lhblang -lhbrdd \ -lhbmacro -lhbpp -lhbcommon -lrddntx -lrddcdx -lrddfpt -lhbsix \ -lhbct -lgttrm -lhbcpage -Wl,--end-group -lm -lgpm
Hbmk2
[править]С помощью Hbmk2 все немного проще. Чтобы откомпилировать программу из одного prg — файла (например, hello.prg), просто наберите:
hbmk2 hello.prg
Из двух prg:
hbmk2 mymain.prg second.prg
Построить приложение, используя специальный конфигурационный файл проекта:
hbmk2 myapp.hbp
Построить приложение, используя свою библиотеку:
hbmk2 myapp.prg -lmylib -L
Построить приложение, из всех prg и c файлов, расположенных в каталоге src:
hbmk2 -omyapp src/*.prg src/*.c
Hbmk2 сама определяет, какой C компилятор у вас установлен, она ищет путь к нему в переменной окружения PATH. Если у вас больше, чем один установленный C компилятор и хотите указать, какой именно должна использовать hbmk2, пропишите параметр -comp=<name>, где <name> — условное обозначения компилятора, например:
— для Windows: mingw, msvc, bcc, watcom, icc, pocc, xcc, mingw64, msvc64, msvcia64, iccia64, pocc64;
— для Linux: gcc, clang, icc, watcom, sunpro, open64, pcc.
Очень полезная опция -trace выводит на экран все вызовы компиляторов и линкера со всеми их опциями, которые потребовались для сборки данного проекта — так вам проще разобраться в проблемах, если что-то пошло не так, ну и вообще, на мой взгляд, полезно знать, как именно строилось ваше приложение.
Как использовать динамические библиотеки (dll, so)
[править]В результате процесса сборки, описанного в предыдущих подразделах, вы получаете исполняемый модуль, который включает в себя ваши исходный тексты, скомпилированные в p-code, виртуальную машину Harbour, которая исполняет этот p-code, RTL — Run-Time Library — библиотеку функций Harbour и, возможно, другие библиотеки, которые вы включили в проект. Поэтому этот исполняемый модуль имеет довольно-таки большой размер. Его можно существенно уменьшить, если использовать динамическую библиотеку. Бинарные дистрибутивы Harbour включают, помимо статических библиотек (.lib, .a) и динамическую (.dll, .so), которая включает в себя все функции основных библиотек Harbour. Ее название может включать в себя номер версии Harbour и название C компилятора; так, например, для Harbour 2.1, построенного с Borland C, это harbour-21-bcc.dll. Естественно, использоваться такой исполняемый модуль может только совместно с соответствующей динамической библиотекой.
Итак, наш bat’ник для компиляции одного prg c Borland C приобретает такой вид:
@set HB_BIN_INSTALL=d:\harbour\bin @set HB_LIB_INSTALL=d:\harbour\lib @set HB_INC_INSTALL=d:\harbour\include\ %HB_BIN_INSTALL%\harbour %1.prg -n -i%HB_INC_INSTALL% bcc32 -O2 -d -I%HB_INC_INSTALL% -L%HB_LIB_INSTALL% %1.c hbmainstd.lib harbour-21-bcc.lib
Отличие состоит в том, что вместо длинного списка библиотек мы используем теперь только две — hbmainstd.lib и harbour-21-bcc.lib. Последняя представляет собой так называемую import library — библиотеку — указатель на функции из соответствующей dll. Такую библиотеку требуют для статической линковки с dll некоторые C компиляторы, в том числе Borland C и MSVC. Mingw и GNU C, кстати, этого не требуют. Название этой библиотеки может быть другим, если у вас другая версия Harbour — harbour-32-bcc.lib, например. Не буду здесь пояснять, для чего нужна hbmainstd.lib — все таки это Harbour для начинающих :), скажу только, что для некоторых GT, gtwvt, например, вместо нее нужно использовать hbmainwin.lib.
Для Mingw C компилятора замените последнюю строчку на:
gcc -Wall -mno-cygwin -c -I%HB_INC_INSTALL% %1.c gcc -Wall -mwindows -o%1%.exe %1.o %HB_BIN_INSTALL%/win/mingw/harbour-21.dll -L%HB_LIB_INSTALL%/win/mingw -Wl,--start-group -lhbmainstd -luser32 -lgdi32 -lwinspool -lcomctl32 -luuid -lkernel32 -lws2_32 -Wl,--end-group
Для Unix/Linux и GNU C это будет выглядеть так:
#!/bin/sh HB_INS="/apps/harbour" $HB_INS/bin/harbour $1.prg -n -q0 -es2 -gc0 -I$HB_INS/include -I../include -d__LINUX__ gcc -I. -I$HB_INS/include -Wall -c $1.c -o$1.o gcc -Wall -o$1 $1.o $HB_INS/lib/libharbour-2.1.0.so -lm -lgpm
то есть весь список библиотек мы заменили на libharbour-2.1.0.so (для другой версии Harbour название, соответственно, будет другим) — сама динамическую библиотеку, import library, здесь не нужна.
С hbmk2 все существенно проще. Независимо от платформы и компилятора:
hbmk2 hello.prg -shared
Теперь о другом варианте использования динамических библиотек — о так называемых p-code dll. Вы можете откомпилировать и собрать часть ваших prg в динамическую библиотеку (dll или so) и затем использовать ее со своими приложениями; такую динамическую библиотеку мы и называем p-code dll.
Итак, мы имеем файл mylib.prg с функцией M1(), который мы хотим собрать в виде p-code dll с тем, чтобы впоследствии использовать его с главным приложением myapp.prg:
// mylib.prg FUNCTION M1 ? "Это функция из динамической библиотеки " + Procname() inkey(0) RETURN Nil
Наше главное приложение myapp может быть собрано со статическими библиотеками или с Harbour dll (so), как было описано в начале этого подраздела. Здесь мы рассмотрим второй вариант, когда myapp собирается с Harbour dll, поскольку первый требует пересборку Harbour с ключом set HB_USER_CFLAGS=-DHB_DYNLIB. У нас есть 2 способа сборки myapp с mylib — со статическим связыванием и с динамическим связыванием. Статическое связывание динамической библиотеки — это звучит немного странно :), но я поясню, что имеется ввиду. Статическое связывание предполагает, что уже на стадии линковки (терпеть не могу это слово, но у него недостаточно синонимов на русском) разрешаются все ссылки на внешние функции. Как уже говорилось выше, некоторые компиляторы, в частности, Borland C, MSVC, требуют для этого предварительного создания import library — статической библиотеки со ссылками на функции в соответствующей динамической библиотеке; именно эта import library будет прилинковываться к главному приложению, чтобы обеспечить статическое связывание. При статическом связывании наличие «привязанной» динамической библиотеки необходимо для запуска программы, независимо от того, будете ли вы в текущем сеансе работы использовать функции из нее или нет; без этой библиотеки ваше приложение выдаст соответствующее предупреждение и не запустится. При динамическом связывании ссылки на внешние функции разрешаются во время исполнения, надо только перед использованием этих функций загрузить динамическую библиотеку с помощью функции hb_LibLoad(), ну и не забыть потом ее выгрузить при помощи hb_LibFree(). В этом случае наличие динамической библиотеки потребуется не при запуске программы, а в тот момент, когда будет выполняться hb_LibLoad(), если она вообще будет выполняться. При таком подходе можно сэкономить на времени загрузки программы и на занимаемой ею памяти — подгружая динамические модули только по мере необходимости.
При рассмотрении способов сборки будем пока для простоты пользоваться Hbmk2. Итак, статическое связывание. Собираем сначала саму динамическую библиотеку. Для Borland C и MSVC нам надо, как вы помните, создать еще и import library, поэтому пишем в командной строке:
hbmk2 mylib.prg -shared -hbdynvm -nohblib -implib
Результатом этой команды станет появление mylib.dll и mylib.lib, где последняя и есть import library; опция «-implib» как раз указывает hbmk2 создать эту библиотеку. Для других компиляторов (Mingw, GNU C) пишем:
hbmk2 mylib.prg -shared -hbdynvm -nohblib -olibmylib
то есть то же самое, но без «-implib», в результате получаем на выходе libmylib.dll (или libmylib.so для Linux GNU C).
Теперь нам надо построить само приложение myapp, статически связав его с mylib.
// myapp.prg FUNCTION Main hb_cdpSelect("RU866") M1() RETURN Nil
Делаем это следующим образом (для Borland C и MSVC):
hbmk2 myapp.prg -shared -lmylib.lib
или (для Mingw, GNU C):
hbmk2 myapp.prg -shared -L. -lmylib
Теперь динамическое связывание. Саму динамическую библиотеку строим так же, как и для статического связывания, только нет нужды использовать «-implib», так как нам не нужна import library. А вот myapp.prg придется изменить, так как нам надо загружать динамическую библиотеку при помощи hb_LibLoad():
// myapp.prg DYNAMIC M1 FUNCTION Main Local hLib hb_cdpSelect("RU866") hLib := hb_LibLoad( "mylib.dll" ) if !empty( hLib ) M1() endif hb_LibFree( hLib ) RETURN Nil
Обратите внимание на строчку DYNAMIC M1. Поскольку мы не будем прилинковывать к нашей myapp.prg никакую библиотеку, а загрузим ее динамически, то для того, чтобы линкер не ругался на неразрешенные ссылки, мы должны объявить все функции из динамической библиотеки, которые мы собираемся использовать, как DYNAMIC. Строим наше приложение (заметьте, никакого упоминания mylib, так как она привязывается не статически во время линковки, а динамически — во время исполнения) :
hbmk2 myapp.prg -shared