Программирование: Использование DLL файлов

При помощи Pascal-сценариев можно вызывать функции из внешних библиотек DLL. Сюда относятся как стандартные функции Windows API из системных библиотек Windows, так и пользовательские функции из пользовательских библиотек DLL.

Пример использования внешних библиотек DLL показан в файле сценария "CodeDll.iss" из папки "Examples" по месту установки Inno Setup.

Папка "Examples" также содержит два примера проекта создания пользовательских DLL: один для Microsoft Visual C++ и один для Embarcadero Delphi.

Для вызова функции из библиотеки DLL сначала, как обычно, следует записать прототип функции, но вместо тела функции необходимо использовать ключевое слово 'external' и указать DLL. Если, к примеру, функция имеет прототип function A(B: Integer): Integer;, то для неё поддерживаются следующие три формы:

[Code]
function A(B: Integer): Integer;
external '<dllfunctionname>@<dllfilename>';

function A(B: Integer): Integer;
external '<dllfunctionname>@<dllfilename> <callingconvention>';

function A(B: Integer): Integer;
external '<dllfunctionname>@<dllfilename> <callingconvention> <options>';

Первая форма определяет вызов DLL-функции с использованием соглашения о вызовах по умолчанию.

Вторая форма определяет вызов DLL-функции с использованием специального соглашения о вызовах. Допустимыми соглашениями о вызовах являются: 'stdcall' (по умолчанию), 'cdecl', 'pascal' и 'register'. Все стандартные 32-разрядные функции Windows API используют 'stdcall', как и многие пользовательские 32-разрядные функции DLL. Для 64-разрядных функций Windows API и пользовательских файлов DLL соглашение об вызове все ещё может быть указано, но оно игнорируется, поскольку все 64-разрядные функции всегда используют одно и то же соглашение об вызовах.

Третья форма определяет один или несколько дополнительных параметров загрузки DLL, разделённых пробелами:

delayload

Определяет отложенную загрузку библиотеки DLL. Как правило, при запуске Pascal-сценарий проверяет доступность вызываемых DLL-функций и в случае отсутствия одной из них прекращает свою работу. Этого не произойдёт, если указать отложенную загрузку 'delayload': библиотека будет загружена не сразу, а только при первом обращении к функции. Используйте отложенную загрузку, когда не знаете, что при выполнении вызываемая DLL-функция будет фактически доступной. В случае невозможности её вызова Pascal-сценарий продолжит свою работу, но вызовет исключение, которое можно перехватить и корректно обработать отсутствие DLL-функции.

loadwithalteredsearchpath

Определяет загрузку библиотеки DLL с флагом LOAD_WITH_ALTERED_SEARCH_PATH, который, по сути, заставляет загрузчик выполнять поиск зависимых DLL, начиная с каталога, в котором находится DLL.

setuponly

Определяет загрузку библиотеки DLL только при выполнении сценария из программы установки.

uninstallonly

Определяет загрузку библиотеки DLL только при выполнении сценария из программы удаления.

Например (вторая форма), если в библиотеке DLL функция называется 'A2', файл DLL имеет имя 'MyDll.dll' и DLL-функция использует соглашение о вызовах 'stdcall', то код записывается следующим образом:

[Code]
function A(B: Integer): Integer;
external 'A2@MyDll.dll stdcall';

Имя файла DLL может содержать константы.

При установке можно использовать специальную приставку 'files:', чтобы инструктировать программу установки автоматически извлекать один или более файлов DLL, указанных в секции [Files], до загрузки первой библиотеки DLL. Например:

[Files]
Source: "MyDll.dll"; Flags: dontcopy noencryption
Source: "A.dll"; Flags: dontcopy noencryption
Source: "B.dll"; Flags: dontcopy noencryption

[Code]
procedure MyDllFunc(hWnd: HWND; lpText, lpCaption: AnsiString; uType: Cardinal);
external 'MyDllFunc@files:MyDll.dll stdcall';

procedure ADllFunc(hWnd: HWND; lpText, lpCaption: AnsiString; uType: Cardinal);
external 'ADllFunc@files:A.dll,B.dll stdcall loadwithalteredsearchpath'; //A.dll зависит от B.dll   

Когда используется приставка 'files:' и включено непрерывное сжатие, постарайтесь разместить все файлы DLL в начале списка файлов секции [Files]. Чтобы извлечь произвольный файл в инсталляторе с непрерывным сжатием, программа установки должна будет сперва распаковать все предыдущие файлы, используя временный буфер в памяти. Это может привести к существенной задержке в работе инсталлятора, если перед необходимым файлом DLL перечислен ряд других файлов.

Используйте CreateCallback для выполнения вызова из DLL-функций напрямую в функции вашего сценария (подобно функциям API Windows).

Помимо THandle, для вызова функций Windows API доступны следующие встроенные типы:
DWORD, UINT, BOOL, LONG, ULONG, HANDLE, COLORREF, INT_PTR, LONG_PTR, DWORD_PTR, UINT_PTR, ULONG_PTR, LRESULT, HKEY, HINSTANCE, HMODULE, WPARAM, LPARAM, SIZE_T, SSIZE_T, TFileTime, HResult, TGUID, TCLSID, TIID, HBITMAP, HDC, HFONT, and HWND.