Статьи Королевства Дельфи

Как прекрасна была бы жизнь,


Как прекрасна была бы жизнь, если б можно было все насущные нужды разработчика удовлетворить только средствами языка разработки! Увы, нет в мире совершенства, как говорил Лис, и поэтому фирмы-разработчики средств разработки генерируют всё новые, всё более мощные среды разработки (IDE), а также развивают сами языки программирования - взять те же Delphi, BCB, C# : сравните языковые средства с Pascal и C++. Вспомните также, сколько дополнительных (встроенных в IDE и отдельных) инструментальных средств входит в поставку BCB и Delphi.
Borland Software Corporation, отдав дань уважения OWL, задвинула её подальше и стала развивать Delphi и BCB на платформе VCL. Совершенно не вижу, почему бы благородным донам не поступить так же J.
Суть моего решения состоит в интеграции средства языка - компоненты - и дополнительного инструментального средства собственной разработки - DllWizard. Интерфейс-оболочку к DLL обеспечивает компонента TAskDll (исходный код - в архиве AskDll.zip). В её методах инкапсулированы:
  • динамическая загрузка DLL (функция LoadLibrary) в методе LoadDll
  • обработка исключительных ситуаций: при возникновении любых проблем с за-грузкой DLL формируется сообщение на языке локализации Windows и генерируется ис-ключение (Exception) для обработки в вызывающем приложении
  • выгрузка DLL и освобождение памяти (функция FreeLibrary), выполняемые авто-матически при прекращении существования компоненты (например, при закрытии формы, на которой расположена компонента)
Загрузка DLL и инициализация импортируемых функций осуществляется вызовом одного лишь метода компоненты - LoadDll. Параметр метода - указатель на функцию: bool (*FuncGetProc)(HMODULE PtrDll) Это должна быть функция вида: bool Example_Load(HMODULE PtrDll) { if((Func1=(DLL_Func1)GetProcAddress(PtrDll, "@Func1$qiii")) == NULL) return false; if((Func2=(DLL_Func2)GetProcAddress(PtrDll, "@Func2$qpct1")) == NULL) return false; return true; }
Всё, что нам нужно - это написать подобный код. Именно эта часть работы наиболее тру-доёмка, и когда мы сможем выполнить её легко, быстро и безошибочно, это и будет красивым венцом нашей технологии.
Задача решается с помощью DllWizard в 3 прохода:
  1. Автоматическое формирование описаний функций с их параметрами и возвращае-мыми значениями.
  2. Автоматическое формирование идентификаторов функций (строковых параметров для функции GetProcAddress)
  3. Генерация исходных текстов
Рассмотрим пример работы с Example.DLL, экспортирующей 2 функции: int __cdecl Func1(int i1, int i2, int i3); char* __cdecl Func2(char *s1, char *s2


Итак, начинаем:
  1. Запускаем DllWizard и создаём список всех функций, которые мы хотим импорти-ровать из DLL. Если DLL собственной разработки, достаточно просто указать путь к её исходнику и нажать кнопку "Найти": список сформируется автоматически (см.Рисунок 1)
  2. Указываем путь к DLL и нажимаем кнопку "Найти" (см.Рисунок 2)
  3. Нажимаем кнопку "Сгенерировать" - в каталогах, указанных на закладке "На-стройки" будут сформированы файлы

Рисунок 1

Рисунок 2
Имя DLL-ки является префиксом у всех сгенерированных файлов и у функции в модуле CPP. Исходный текст DLL и тестового приложения находится в архиве DllTest.zip
Подкаталог DLL содержит исходный текст библиотеки: UnitExample.cpp Подкаталог EXE содержит исходный текст тестового приложения: UnitDllTest.cpp и в подкаталоге DllWizard - сгенерированные файлы:
  1. Заголовочные файлы:
  1. Example_Descript.h является служебным и содержит описание функций
  2. Example_Declare.h является служебным и содержит объявления указателей на функции
  3. Example_Extern.h следует включить в тот исходный модуль проекта прило-жения, из которого вызываются функции, импортируемые из DLL.
  • Example_Load.cpp содержит функцию загрузки Example_Load


  • Содержание раздела