Динамическое подключение DLL
Чтобы поток мог вызвать функцию из DLL-модуля, последний нужно спроецировать на адресное пространство процесса, которому принадлежит этот поток. Сделать это можно двумя способами. Первый состоит в том, что при разработке приложения декларативно объявляется, какие DLL будут использованы. Это заставляет загрузчик загружать (и связывать) нужные DLL при запуске приложения. Другой способ – динамическая загрузка и связывание требуемой DLL во время выполнения приложения. Особенность данного подхода в том, что загрузка DLL может выполняться отложено. В любой момент поток может спроецировать DLL на адресное пространство процесса, вызвав одну из функций: HINSTANCE LoadLibrary(PCSTR dllFileName); HINSTANCE LoadLibraryEx(PCSTR dllFileName, HANDLE hFile, DWORD flags); Обе функции производят поиск DLL-файла dllFileName и пытаются спроецировать его на адресное пространство вызывающего процесса. Возвращаемое значение типа HINSTANCE сообщает адрес виртуальной памяти, по которому спроецирован образ файла. Если имя DLL-файла dllFileName указано не полностью, поиск DLL осуществляется в следующей последовательности: 1. Каталог, содержащий exe-файл вызывающего процесса. 2. Текущий каталог вызывающего процесса. 3. Системный каталог Windows. 4. Основной каталог Windows. 5. Каталоги, перечисленные в переменной окружения Path. Параметр hFile функции LoadLibraryEx зарезервирован для использования в будущих версиях и должен быть равен NULL. Параметр flags определяет режим работы функции, то есть то, как именно должна быть загружена указанная DLL. Если необходимость в DLL отпадает, ее можно выгрузить из адресного пространства процесса, вызвав функцию FreeLibrary: BOOL FreeLibrary(HINSTANCE hModule); Параметр hModule идентифицирует выгружаемую DLL. Для получения адреса экспортируемого идентификатора из динамически загруженной DLL, необходимо вызвать функцию GetProcAddress: FARPROC GetProcAddress(HMODULE hModule, PCSTR procName); Параметр hModule идентифицирует DLL-модуль, в котором производится поиск функции с именем procName. Результатом работы GetProcAddress служит адрес содержащегося в DLL идентификатора. Если идентификатор не найден, возвращается NULL. Ниже приведен код, в котором производится динамическая загрузка DLL-модуля, после чего осуществляется поиск и вызов определенной в нем функции: // Описание прототипа импортируемой функции typedef void (*ShowDialogFunction)(char[], char[]);
...
// Загрузка DLL HINSTANCE hModule = LoadLibrary("SomeDll.dll");
if (hModule != NULL) { // Поиск адреса функции ShowDialogFunction ShowDialog = (ShowDialogFunction)GetProcAddress(hModule, "ShowDialog");
if (ShowDialog != NULL) { ShowDialog("Text", "Caption"); }
// Выгрузка DLL FreeLibrary(hModule); } Естественно, что такой подход предполагает, что вызывающий код знает о том, какой прототип имеет искомая функция. ©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.
|