|
Внешние модули (DLL), нити
|
|
Главная страница \ Системное программирование \ Внешние модули (DLL), нити |
Как написать свой PlugIN (типа поддержки различных форматов файлов ...) | * | * |
Типовая задача - разрабатывается некая задача и при этом
Классические примеры - фильтры для совместимости по форматам файлов с другими программами, некоторые расширения и дополнительные возможности. Примеры и моей практики - приведу парочку
Итак, все это можно реализовать в DLL, однако обычное ее подключение приведет к тому, что при запуске программа будет искать все подключенне к ней DLL и в случае отсутствия хотя-бы одной откажется запускаться. Это не приемлемо, но к счастю есть возможность и весьма удоюный набор сервисных функций для динамической загрузки, использования и выгрузки DLL.
Пример (приложение имеет одно окно, на нем кнопка):
unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormCreate(Sender: TObject); private public end; // Тип "процедура". Естественно, можно определит типы // "функция" или "функция с параметрами" ... TDllProc = procedure; var Form1: TForm1; DllProcPtr : TDllProc; LibInstance : HMODULE; // Логический номер модуля DLL implementation {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); begin // Проверим, загружена ли DLL if LibInstance=0 then Begin // Не загружена, попробуем загрузить LibInstance := LoadLibrary('plug_in.dll'); // Проверим, успешна ли загрузка (LibInstance=0 - неуспешно) If LibInstance=0 then Begin ShowMessage('Ошибка загрузки библиотеки plug_in.dll'); exit; end; // Ищем функцию по ее имени (имя должно точно совпадать) DllProcPtr := TDllProc(GetProcAddress(LibInstance,'MyProc')); // Проверим, нашли ли (если нашли, то Assigned вернет true) if not Assigned(DllProcPtr) then Begin // Не нашли - выгружаем DLL из памяти FreeLibrary(LibInstance); LibInstance:=0; ShowMessage('Ошибка: функция MyProc не найдена'); exit; end; // Непосредственно вызов функции DllProcPtr; // Выгрузка библиотеки FreeLibrary(LibInstance); LibInstance:=0; end; end; procedure TForm1.FormCreate(Sender: TObject); begin DllProcPtr:=nil; LibInstance:=0; end; end.
Естественно, в реальной задаче имеет смысл создать свой класс, который при инициализации будет загружать библиотеку, а при уничтожении - выгружать. Кроме того, он должен иметь функцию типа "Перезагрузить библиотеку", которая будет выгружать текущую и загружать новую. DLL - обычная, естественно может иметь неограниченное количество процедур и функций.
Особенности: