Здравствуйте уважаемые коллеги!
В данной статье я постараюсь ответить на вопросы: Что такое DLL? Для чего она нужна? И как создавать и использовать DLL при помощи Delphi.
Что такое DLL?
Dynamic Link Library или сокращенно DLL — это библиотека, которая содержит в себе набор данных или функций для использования в других программах.
Области применения:
- Хранение ресурсов: иконки, звуки, курсоры и т.д. Экономим на размере исполняемых файлов объединяя ресурсы в единую библиотеку.
- Размещение отдельных модулей программы и форм интерфейса. Получаем возможность частичного обновления приложения, а при динамическом подключении, возможно обновлять модули без перезапуска основной программы.
- Использование в качестве плагинов (PlugIn). Предоставляем возможность расширять функционал приложения без переписывания основного кода программы.
- Библиотека может использоваться на разных языках программирования в не зависимости от языка на котором она была написана.
Создание собственной библиотеки DLL.
Для создания библиотеки заходим в меню File -> Other и выбираем Delphi Projects -> Dynamic-link Library.
Откроется текст кода с заготовкой для создания библиотеки:
library Project1; uses System.SysUtils, System.Classes; {$R *.res} begin end.
Размещение ресурсов
Добавим иконку в библиотеку, которую будем использовать потом в основной программе.
Как добавлять ресурсы в проект подробно описано в этой статье.
Добавим форму «О программе».
Нажимаем File -> New -> VCL Form. Добавим текст и кнопку «ОК»:
Добавим функцию, которая будет выводить стандартный MessageBox с вопросом, кнопками «Да», «Нет» и с результатом в виде True или False.
function YesNoDlg(const Question: PChar): boolean; stdcall; begin Result := (MessageBox(0, Question, 'Подтверждение', MB_YESNO + MB_ICONQUESTION) = ID_YES); end;
Обратите внимание на ключевое слово stdcall. Оно определяет как именно будут передаваться параметры и результаты при вызове функций. Более подробно можно почитать на странице wiki Соглашение о вызове.
Так же добавим процедуру, которая будет использоваться как плагин для основной программы. Которая будет добавлять кнопку «О программе» в основное меню программы для вызова созданного нами окна.
Код процедуры:
procedure PlugIn(Form: TForm); stdcall; var i: integer; mi: TMenuItem; begin for i := 0 to Form.ComponentCount - 1 do begin if (Form.Components[i].ClassName = 'TMenuItem') and (Form.Components[i].Name = 'miHelp') then begin mi := TMenuItem.Create(Form.Components[i]); mi.Caption := 'О программе'; mi.OnClick := fmAbout.onAboutButtonClick; TMenuItem(Form.Components[i]).Add(mi); Exit; end; end; end;
В процедуру в качестве параметра передается форма программы. Мы проверяем присутствует ли на ней пункт меню с именем «miHelp» и если меню нашлось, то добавляем в него свою кнопку.
Теперь укажем какие функции и процедуры можно использовать из нашей библиотеки.
Добавим строку:
exports PlugIn, YesNoDlg;
Скомпилируем функцию Project -> Build или с помощью горячей клавиши Shift+F9.
Если ошибок в коде нет, то в папке проекта должен появиться файл с расширением DLL.
Теперь перейдем к созданию приложения, которое будет использовать нашу библиотеку.
В приложении создадим форму Main в которой добавим компонент TMainMenu со следующими кнопками: Программа -> Выход и Помощь. Для последнего зададим имя — miHelp:
Перейдем к коду формы.
Функции из библиотеки DLL можно подключать двумя способами:
Статическим — библиотека подключается при запуске программы. Если библиотека или имя функции не найдено, то программа выдаст ошибку и не запустится.
Динамическим — библиотека подключается или непосредственно перед вызовом функции или по определенному событию.
Рассмотрим статический способ подключения:
... type TfmMain = class(TForm) MainMenu: TMainMenu; miProgram: TMenuItem; miExit: TMenuItem; miHelp: TMenuItem; procedure FormCreate(Sender: TObject); procedure miExitClick(Sender: TObject); private public end; procedure PlugIn(Form: TForm); stdcall; external 'SampleDLL.dll'; var ...
Ключевое слово external указывает на то, что данная функция подключается из внешней библиотеки.
На событие onCreate формы добавим вызов процедуры PlugIn:
procedure TfmMain.FormCreate(Sender: TObject); begin PlugIn(Self); end;
В качестве параметра Form передаем в процедуру текущую форму (ключевое слово Self).
При запуске программы у нас должен появится пункт «О программе» в разделе «Помощь» главного меню.
Переходим к динамическому способу подключения.
Нам понадобятся три функции WinApi:
LoadLibrary
Загружает библиотеку в память компьютера. В качестве результата возвращает указатель на библиотеку в памяти. В случае ошибки вернет 0.
LoadLibrary( lpLibFileName: LPCWSTR ): HMODULE;
lpLibFileName — Имя файла библиотеки.
GetProcAddress
Найти функцию в библиотеки по имени. Результатом будет указатель на функцию. Если функция не найдена, то вернет nil.
GetProcAddress( hModule: HMODULE; lpProcName: LPCSTR ): FARPROC;
hModule — Указатель на загруженную библиотеку.
lpProcName — Имя функции.
FreeLibrary
Выгружает библиотеку из памяти компьютера. Результатом будет True в случае успешного выполнения и False в случае ошибки.
FreeLibrary( hLibModule: HMODULE ): BOOL;
hLibModule — Указатель на загруженную библиотеку.
Теперь с помощью динамического способа получим ресурсы, нашу иконку и на кнопку «Выход» добавим вызов функции YesNoDlg для подтверждения закрытия программы.
На то же событие onCreate добавляем код:
procedure TfmMain.FormCreate(Sender: TObject); var DLLHandle: THandle; begin PlugIn(Self); DLLHandle := LoadLibrary('SampleDLL.dll'); if DLLHandle = 0 then raise Exception.Create('Не удалось подключить библиотеку "SampleDLL"!'); try Self.Icon.LoadFromResourceName(DLLHandle, 'my_icon'); finally FreeLibrary(DLLHandle); end; end;
И на событие onClick пункта меню «Выход»:
procedure TfmMain.miExitClick(Sender: TObject); var DLLHandle: THandle; Dlg: function(const Question: PChar): boolean; stdcall; begin DLLHandle := LoadLibrary('SampleDLL.dll'); if DLLHandle = 0 then raise Exception.Create('Не удалось подключить библиотеку "SampleDLL"!'); try @Dlg := GetProcAddress(DLLHandle, 'YesNoDlg'); if not Assigned(@Dlg) then raise Exception.Create('Функция с именем "YesNoDlg" не найдена в библиотеке "SampleDLL"!'); if Dlg('Выйти из программы?') then Close; finally FreeLibrary(DLLHandle); end; end;
Если вы все написали верно, то после запуска программы должна поменяться иконка формы, добавиться кнопка «О программе», при нажатии на которую будет показывать форма About и на нажатие кнопки выход программа будет запрашивать подтверждение: «Выйти из программы?».
Надеюсь вам будет полезен этот небольшой пример использования возможностей DLL библиотек.
Исходники проекта можно скачать тут.
Спасибо за информацию!!!!!