Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ГОС_ответы.doc
Скачиваний:
43
Добавлен:
27.10.2018
Размер:
21.59 Mб
Скачать

32 Динамічний імпорт функцій при використанні dll-бібліотек.

В некоторых случаях невозможно выполнить динамическую компоновку на этапе редактирования. Вы можете, например, создать приложение, которое состоит из основного модуля и дополнительных, реализованных в виде DLL-библиотек. Состав этих дополнительных модулей и имена файлов, содержащих DLL-библиотеки, может изменяться, при этом в приложение могут добавляться новые возможности.

Приложение может в любой момент времени загрузить любую DLL-библиотеку, вызвав специально предназначенную для этого функцию программного интерфейса Windows с именем LoadLibrary. Приведем ее прототип:

HINSTANCE WINAPI LoadLibrary(LPCSTR lpszLibFileName);

Параметр функции является указателем на текстовую строку, закрытую двоичным нулем. В эту строку перед вызовом функции следует записать путь к файлу DLL-библиотеки или имя этого файла. Если путь к файлу не указан, при поиске выполняется последовательный просмотр следующих каталогов:

·       каталог, из которого запущено приложение;

·       текущий каталог;

·       32-разрядный системный каталог Microsoft Windows NT;

·       16-разрядный системный каталог;

·       каталог в котором находится операционная система Windows NT;

·       каталоги, перечисленные в переменной описания среды PATH

Если файл DLL-библиотеки найден, функция LoadLibrary возвращает идентификатор модуля библиотеки. В противном случае возвращается значение NULL. При этом код ошибки можно получить при помощи функции GetLastError.

Функция LoadLibrary может быть вызвана разными приложениями для одной и той же DLL-библиотеки несколько раз.

Пример загрузки DLL-библиотеки из файла DLLDEMO.DLL:

typedef HWND (WINAPI *MYDLLPROC)(LPSTR);

MYDLLPROC GetAppWindow;

HANDLE hDLL;

hDLL = LoadLibrary("DLLDEMO.DLL");

if(hDLL != NULL)

{ GetAppWindow = (MYDLLPROC)GetProcAddress(hDLL, "FindApplicationWindow");

if(GetAppWindow != NULL)

{ if(GetAppWindow(szWindowTitle) != NULL)

MessageBox(NULL, "Application window was found", szAppTitle, MB_OK);

else

MessageBox(NULL, "Application window was not found", szAppTitle, MB_OK);

} FreeLibrary(hDLL);}

Здесь вначале с помощью функции LoadLibrary выполняется попытка загрузки DLL-библиотеки DLLDEMO.DLL. В случае успеха приложение получает адрес точки входа для функции с именем FindApplicationWindow, для чего используется функция GetProcAddress. Если точка входа получена, функция вызывается через указатель GetAppWindow. После использования DLL-библиотека освобождается при помощи функции FreeLibrary, прототип которой показан ниже:

void WINAPI FreeLibrary(HINSTANCE hLibrary);

В качестве параметра этой функции следует передать идентификатор освобождаемой библиотеки.

При освобождении DLL-библиотеки ее счетчик использования уменьшается. Если этот счетчик становится равным нулю (что происходит, когда все приложения, работавшие с библиотекой, освободили ее или завершили свою работу), DLL-библиотека выгружается из памяти.

Каждый раз при освобождении DLL-библиотеки вызывается функция DLLEntryPoint с параметрами DLL_PROCESS_DETACH или DLL_THREAD_DETACH, выполняющая все необходимые завершающие действия.

Для того чтобы вызвать функцию из библиотеки, зная ее идентификатор, необходимо получить значение дальнего указателя на эту функцию, вызвав функцию GetProcAddress:

FARPROC WINAPI GetProcAddress(HINSTANCE hLibrary,

LPCSTR lpszProcName);

Через параметр hLibrary вы должны передать функции идентификатор DLL-библиотеки, полученный ранее от функции LoadLibrary.

Параметр lpszProcName является дальним указателем на строку, содержащую имя функции или ее порядковый номер, преобразованный макрокомандой MAKEINTRESOURCE.

Пример определения адреса двух функций. В первом случае используется имя функции, а во втором - ее порядковый номер:

FARPROC lpMsg;

FARPROC lpTellMe;

lpMsg = GetProcAddress(hLib, "Msg");

lpTellMe = GetProcAddress(hLib, MAKEINTRESOURCE(8));

Перед тем как передать управление функции по полученному адресу, следует убедиться в том, что этот адрес не равен NULL:

if(lpMsg != (FARPROC)NULL)

{

(*lpMsg)((LPSTR)"My message");}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]