Главная » Win32 API » Вызов функций из DLL

0

Существует три способа загрузки DLL:

а) неявная;

б)  явная;

в) отложенная.

Рассмотрим неявную загрузку DLL. Для построения приложения, рассчитанного на неявную загрузку DLL, необходимо иметь:

•            Библиотечный включаемый файл с описаниями используемых объектов из DLL (прототипы функций, объявления классов и типов). Этот файл используется компилятором.

•            LIB-файл со списком импортируемых идентификаторов. Этот файл нужно добавить в настройки проекта (в список библиотек, ис­пользуемых компоновщиком).

Компиляция проекта осуществляется обычным образом. Используя объектные модули и LIB файл, а также учитывая ссылки на импор­тируемые идентификаторы, компоновщик (линкер, редактор связей) формирует загрузочный ЕХЕ модуль. В этом модуле компоновщик помещает также раздел импорта, где перечисляются имена всех необ­ходимых DLL-модулей. Для каждой DLL в разделе импорта указыва­ется, на какие имена функций и переменных встречаются ссылки в ко­де исполняемого файла. Эти сведения будет использовать загрузчик операционной системы.

Что же происходит на этапе выполнения клиентского приложения? После запуска ЕХЕ-модуля загрузчик операционной системы выпол­няет следующие операции:

1.                    Создает виртуальное адресное пространство для нового про­цесса и проецирует на него исполняемый модуль;

2.                    Анализирует раздел импорта, определяя все необходимые DLL-модули и тоже проецируя их на адресное пространство процесса.

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

После отображения ЕХЕ-модуля и всех DLL-модулей на адресное пространство процесса его первичный поток готов к выполнению, и приложение начинает работу.

Недостатками неявной загрузки являются обязательная загрузка библиотеки, даже если обращение к ее функциям не будет происхо­дить, и, соответственно, обязательное требование к наличию библио­теки при компоновке.

Явная загрузка DLL устраняет отмеченные выше недостатки за счет некоторого усложнения кода. Программисту приходится самому заботиться о загрузке DLL и подключении экспортируемых функций. Зато явная загрузка позволяет подгружать DLL по мере необходимо­сти и дает возможность программе обрабатывать ситуации, возни­кающие при отсутствии DLL.

В случае явной загрузки процесс работы с DLL происходит в три этапа:

1.                    Загрузка DLL с помощью функции LoadLibrary (или ее рас­ширенного аналога LoadLibraryEx). В случае успешной загрузки функция возвращает дескриптор hLib типа HMODULE , что позволяет в дальнейшем обращаться к этой DLL.

2.                    Вызовы функции GetProcAddress для получения указателей на требуемые функции или другие объекты. В качестве первого пара­метра функция GetProcAddress получает дескриптор hLib, в качестве второго параметра -адрес строки с именем импортируемой функции. Далее полученный указатель используется клиентом. Например, если это указатель на функцию, то осуществляется вызов нужной функции.

3.                    Когда загруженная динамическая библиотека больше не нуж­на, рекомендуется ее освободить, вызвав функцию FreeLibrary. Осво­бождение библиотеки не означает, что операционная система немед­ленно удалит ее из памяти. Задержка выгрузки предусмотрена на тот случай, когда эта же DLL через некоторое время вновь понадобится какому-то процессу. Но если возникнут проблемы с оперативной па­мятью, Windows в первую очередь удаляет из памяти освобожденные библиотеки.

Рассмотрим отложенную загрузку DLL. DLL отложенной загрузки (delay-load DLL) это неявно связываемая DLL, которая не загружает­ся до тех пор, пока код не обратится к какому-нибудь экспортируемо­му из нее идентификатору. Такие DLL могут быть полезны в следую­щих ситуациях:

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

•            Если приложение предназначено для работы в различных вер­сиях ОС, то часть функций может появиться лишь в поздних версиях ОС и не использоваться в текущей версии. Но если программа не вы­зывает конкретной функции, то DLL ей не нужна, и она может спо­койно продолжать работу. При обращении же к несуществующей

функции можно предусмотреть выдачу пользователю соответствую­щего предупреждения.

Для реализации метода отложенной загрузки требуется дополни­тельно в список библиотек компоновщика добавить не только нужную библиотеку импорта MyLib.lib, но еще и системную библиотеку им­порта delayimp.lib. Кроме этого, требуется добавить в опциях компо­новщика флаг / delayload:MyLib.dll.

Перечисленные настройки заставляют компоновщик выполнить следующие операции:

•       внедрить       в       ЕХЕ-модуль       специальную       функцию
delayLoadHelper;

•           удалить MyLib.dll из раздела импорта исполняемого модуля, чтобы загрузчик операционной системы не пытался выполнить неяв­ную загрузку этой библиотеки на этапе загрузки приложения;

•           добавить в ЕХЕ-файл новый раздел отложенного импорта со списком функций, импортируемых из MyLib.dll;

•       преобразовать    вызовы    функций    из    DLL    к    вызовам
delayLoadhelper.

На этапе выполнения приложения вызов функции из DLL реализу­ется обращением к delayLoadHelper. Эта функция, используя инфор­мацию из раздела отложенного импорта, вызывает сначала LoadLibrary, а затем GetprocAddress. Получив адрес DLL-функции, delayLoadHelper делает так, чтобы в дальнейшем эта DLL-функция вызывалась напрямую. Отметим, что каждая функция в DLL настраи­вается индивидуально при первом ее вызове.

Источник: Сучкова, Л.И. Win32 API: основы программирования: учебное пособие/ Л.И. Сучкова; АлтГТУ им. ИИ. Ползунова. -Барнаул, АлтГТУ, 2010. 138 с, ил.

По теме:

  • Комментарии