Вход/Регистрация
Программирование на Visual C++. Архив рассылки
вернуться

Jenter Алекс

Шрифт:

В Visual C++ 6.0 появился ещё один способ подключения DLL, сочетающий в себе почти все достоинства двух рассмотренных ранее методов – отложенная загрузка DLL (delay-load DLL). Отложенная загрузка не требует поддержки со стороны операционной системы (а значит будет работать даже под Windows 95), а реализуется линкером Visual C++ 6.0.

При отложенной загрузке DLL загружается только тогда, когда приложение обращается к одной из содержащихся в ней функций. Это происходит незаметно для программиста (то есть вызывать LoadLibrary/GetProcAddress не требуется). После того как работа с функциями библиотеки завершена, её можно оставить в памяти или выгрузить посредством функции __FUnloadDelayLoadedDLL. Вызов этой функции – единственная модификация кода, которую может потребоваться сделать программисту (по сравнению с неявным подключением DLL). Если требуемая DLL не обнаружена, приложение аварийно завершается, но и здесь ситуацию можно исправить, перехватив исключение с помощью конструкции __try/__except. Как видим, отложенная загрузка DLL – весьма удобное средство для программиста.

Теперь рассмотрим, каким образом описанные способы подключения DLL используются на практике. Для этого будем считать, что нам требуется вызвать функцию X, экспортируемую библиотекой MyLib.dll. Пусть функция X имеет простейший прототип: void X(void);

Будем также считать, что библиотека импорта находится в файле MyLib.lib.

Неявное подключение

Первое, что нам нужно сделать – это передать линкеру имя библиотеки импорта нашей DLL. Для этого необходимо открыть окно настройки проекта (Project->Settings) и на вкладке Link дописать "MyLib.lib" в конец списка Object/Library modules. Альтернативный подход заключается в использовании директивы #pragma. В нашем случае необходимо вставить в код программы следующую строку:

#pragma comment(lib,"MyLib")

Второе, что нужно проделать – это добавить объявление функции в код программы (обычно объявления функций, экспортируемых DLL, сводятся в заголовочный файл – тогда требуется просто подключить его). Для нашей функции X объявление выглядит так:

__declspec(dllimport) void X(void);

Вот и всё. Теперь к функции X можно обращаться, как и к любой другой функции, статически прилинкованной к нашей программе:

X;

Явное подключение

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

Загружаем библиотеку:

HINSTANCE hLib = LoadLibrary("MyLib.dll");

Получаем указатель на функцию и вызываем её:

void (*X);

(FARPROC &)X = GetProcAddress(hLib, "X");

X;

Выгружаем библиотеку из памяти:

FreeLibrary(hLib);

Отложенная загрузка

Сначала необходимо повторить шаги, которые мы проделывали при неявном подключении: передать линкеру имя библиотеки импорта и добавить в программу объявление функции X. Теперь, чтобы отложенная загрузка заработала, нужно добавить ключ линкера /DELAYLOAD:MyLib.dll и прилинковать к приложению библиотеку Delayimp.lib, реализующую вспомогательные функции механизма отложенной загрузки. Хотя эти опции можно добавить в настройки проекта, я предпочитаю использовать директивы #pragma:

#pragma comment(lib, "Delayimp")

#pragma comment(linker, "/DelayLoad:MyLib.dll")

Если после вызова функции X нам требуется выгрузить библиотеку MyLib.dll из памяти, можно воспользоваться функцией FUnloadDelayLoadedDLL. Чтобы эта функция работала корректно, необходимо добавить ещё один ключ линкера /DELAY:unload. Кроме того, нужно подключить заголовочный файл , в котором эта функция объявлена. Выглядеть это может примерно так:

#include <Delayimp.h>

#pragma comment(linker, "/Delay:unload")

.

.

X;

__FUnloadDelayLoadedDLL("MyLib.dll");

Имя, передаваемое функции FUnloadDelayLoadedDLL, должно в точности совпадать с именем, указанным в ключе /DELAYLOAD. Так, если передать ей имя "MYLIB.DLL", библиотека останется в памяти.

В заключение хочется отметить ещё один интересный момент. Когда я попытался воспользоваться отложенной загрузкой в своей программе, линкер отказался подключать библиотеку Delayimp.lib, выдавая сообщение о внутренней ошибке и подробную отладочную информацию. Чтобы решить эту проблему, я просто взял файлы Delayhlp.cpp и Delayimp.h из каталога Vc98\Include, добавил в файл Delayhlp.cpp строки:

PfnDliHook __pfnDliNotifyHook = NULL;

PfnDliHook __pfnDliFailureHook = NULL;

и перестроил эту библиотеку заново. После этого отложенная загрузка заработала нормально.

Ссылки

Поскольку я рассказал об отложенной загрузке далеко не все, рекомендую обратиться за дополнительной информацией к следующим статьям в MSDN:

– December 1998, Microsoft systems journal, Win32 Q&A

– December 1998, Microsoft systems journal, Under the hood

  • Читать дальше
  • 1
  • ...
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: