Загрузка DLL с неявной компоновкой
Чтобы вызвать функцию из DLL, ее необходимо объявить в вызывающем коде - либо как external (т. е. как обычную внешнюю функцию), либо предварить ключевым словом __declspec(dllimport). Первый способ более популярен, но второй все же предпочтительнее - в этом случае компилятор, поняв, что функция вызывается именно из DLL, сможет соответствующим образом оптимизировать код. Например, функция "Demo" из созданной нами библиотеки - "MyFirstDll" вызывается так:
// ImplictDll.c
// Объявляем внешнюю функцию Demo
__declspec(dllimport) void Demo(char *str);
main()
{
// Вызываем функцию Demo из DLL
Demo("Hello, World!\n");
}
Демонстрация вызова функции из DLL неявной компоновкой
Из командной строки данный пример компилируется так: "cl.exe ImplictDll.c myfirstdll.lib", где "myfirstdll.lib" - имя библиотеки, автоматически сформированной компоновщиком при создании нашей DLL.
Разумеется, "чужие" DLL не всегда поставляются вместе с сопутствующими библиотеками, но их можно легко изготовить самостоятельно! На этот случай предусмотрена специальная утилита implib, поставляемая вместе с компилятором, и вызываемая так: "implib.exe Имя_файла _создаваемой_библиотеки Имя_DLL".
В нашем случае - не будь у нас файла "MyFirstDLL.lib", его пришлось бы получить так: "implib.exe MyFirstDLL.lib MyFirstDLL.dll". Со всеми стандартными DLL, входящими в состав Windows, эту операцию проделывать не нужно, т.к. необходимые библиотеки распространяются вместе с самим компилятором.
Для подключения библиотеки в интегрированной среде Microsoft Visual Studio - в меню "Project" выберите пункт "Project Settings", в открывшемся диалоговом окне перейдите к закладке "Link" и допишите имя библиотеки в конец строки "Object/Library Modules", отделив ее от остальных символом пробела.
Если все прошло успешно, появится новый файл "ImplictDll.exe", который, будучи запущенным, горделиво выведет на экран "Hello, Word!". Это означает, что наша DLL подключена и успешно работает.
Заглянем внутрь: как это происходит? Запустим "dumpbin /IMPORTS ImplictDll.exe" и посмотрим, что нам сообщит программа:
File Type: EXECUTABLE IMAGE
Section contains the following imports:
myfirstdll.dll
404090 Import Address Table
4044C8 Import Name Table
0 time date stamp
0 Index of first forwarder reference
0 Demo
KERNEL32.dll
404000 Import Address Table
404438 Import Name Table
0 time date stamp
0 Index of first forwarder reference
19B HeapCreate
2BF VirtualFree
CA GetCommandLineA
174 GetVersion
7D ExitProcess
29E TerminateProcess
F7 GetCurrentProcess
Вот - "Myfirstdll.dll" (в тексте выделена жирным шрифтом), и вот функция "Demo", а кроме нее - обнаруживает свое присутствие библиотека KERNEL32.DLL – она необходима RTL-коду (Run Time Library - библиотека времени исполнения), насильно помещенному компилятором в наше приложение. RTL-код обеспечивает работу с динамической памятью (heap), считывает аргументы командной строки, проверяет версию Windows и многое-многое другое! Отсюда и появляются в таблице импорта функции HeapCreate, GetCommandLine, GetVersion и т.д. Так что - не удивляйтесь, увидев "левый" импорт в своем приложении!
Проследить, как именно происходит загрузка DLL, можно с помощью отладчика. Общепризнанный лидер - это, конечно, SoftIce от NuMega, но для наших экспериментов вполне сойдет и штатный отладчик Microsoft Visual Studio. Откомпилировав нашу вызывающую программу, нажмем <F10> для пошагового прогона приложения
Не успело еще выполниться ни строчки кода, как в окне "output" отладчика появились следующие строки, свидетельствующие о загрузке внешних DLL: NTDLL.DLL, MyFirstDll.dll и Kernel32.dll. Так и должно быть - при неявной компоновке динамические библиотеки подключаются сразу же при загрузке файла, задолго до выполнения функции main!
Loaded 'C:\WINNT\System32\ntdll.dll', no matching symbolic information found.
Loaded 'F:\ARTICLE\PRG\DLL.files\myfirstdll.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\kernel32.dll', no matching symbolic information found.
Дата добавления: 2017-01-26; просмотров: 1297;