Загрузка DLL с явной компоновкой
Явную загрузку динамических библиотек осуществляет функция HINSTANCE LoadLibrary(LPCTSTR lpLibFileName) или ее расширенный аналог HINSTANCE LoadLibraryEx(LPCTSTR lpLibFileName, HANDLE hFile, DWORD dwFlags).
Обе они экспортируются из KERNEL32.DLL, следовательно, каждое приложение требует неявной компоновки по крайней мере этой библиотеки. В случае успешной загрузки DLL возвращается линейный адрес библиотеки в памяти. Передав его функции FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName) - мы получим указатель на функцию lpProcName, экспортируемую данной DLL. При возникновении ошибки обе функции возвращают NULL. После завершения работы с динамической библиотекой ее следует освободить вызовом функции BOOL FreeLibrary(HMODULE hLibModule). Для пояснения приведем код примера с подробными комментариями:
// DynCall.c
#include <stdio.h>
#include <windows.h>
main()
{
// Дескриптор загружаемой dll
HINSTANCE h;
// Объявление указателя на функцию, вызываемой из DLL
// Обратите внимание – имена объявляемой функции и
// функции, вызываемой из DLL, могут и не совпадать,
// т.к. за выбор вызываемой функции отвечает
// GetProcAddress
void (*DllFunc) (char *str);
// Загружаем MyFirstDLL
h=LoadLibrary("MyFirstDLL.dll");
// Контроль ошибок – если загрузка прошла успешно,
// функция вернет что-то отличное от нуля
if (!h)
{
printf("Ошибка - не могу найти MyFirstDLL.dll\n");
return;
}
// Вызовом GetProcAddress получаем адрес функции Demo
// и присваиваем его указателю DllFunc с явным
// приведением типов. Это необходимо т.к.
// GetProcAddress возвращает бестиповой far-указатель
DllFunc=(void (*) (char *str))
GetProcAddress(h,"Demo");
// Контроль ошибок – если вызов функции GetProcAddress
// завершился успешно, она вернет ненулевой указатель
if (!DllFunc)
{
printf("Ошибка! В MyFirstDLL "
"отсутствует ф-ция Demo\n");
return;
}
// Вызов функции Demo из DLL
DllFunc("Test");
// Выгрузка динамической библиотеки из памяти
FreeLibrary(h);
}
Демонстрация вызова функции из DLL явной компоновкой
Компилировать так: "cl DynCall.c" - никаких дополнительных библиотек указывать не нужно (необходимые kernel32.lib и LIBC.lib компоновщик подключит самостоятельно).
В интегрированной среде Microsoft Visual Studio достаточно щелкнуть мышкой по иконке "Build" - и никаких дополнительных настроек!
Для изучения секции импорта только что полученного файла запустим утилиту Dumpbin – обратите внимание, что здесь отсутствует всякое упоминание о MyFirstDLL.dll, но обнаруживаются две функции: LoadLibrary и GetProcAddress - которые и загружают нашу библиотеку. Это очень важное обстоятельство - изучение секции импорта исследуемого файла не всегда позволяет установить полный перечень функций и динамических библиотек, которые использует приложение. Наличие LoadLibrary и GetProcAddress красноречиво свидетельствует о том, что приложение подгружает какие-то модули во время работы самостоятельно.
Чтобы выяснить какие - запустим его под отладчиком. Сразу же после загрузки исполняемого файла в окне Output появятся строки:
Loaded 'C:\WINNT\System32\ntdll.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\kernel32.dll', no matching symbolic information found.
Это опять грузятся обязательные KERNEL32.DLL и NTDLL.. Никакого упоминания о MyFirstDLL.dll еще нет. Пошагово исполняя программу ("Debug" ( "Step Over"), дождемся выполнения функции LoadLibrary. Тут же в Output-окне появится следующая строка:
Loaded 'F:\ARTICLE\PRG\DLL.files\myfirstdll.dll', no matching symbolic information found.
Наша динамическая библиотека загрузилась; но не сразу после запуска файла (как это происходило при неявной компоновке), а только когда в ней возникла необходимость!
Если же по каким-то причинам DLL не найдется, или окажется, что в ней отсутствует функция Demo - операционная система не станет "убивать" приложение с "некрологом" критической ошибки, а предоставит программисту возможность действовать самостоятельно. В качестве эксперимента попробуйте удалить (переименовать) MyFirstDLL.dll и посмотрите, что из этого получится.
Дата добавления: 2017-01-26; просмотров: 1475;