Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
основы программирования в Windows.docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
88 Кб
Скачать
☆

§ 1.3. Принципы разработки динамических библиотек

1.3.1. Основные положения

Динамически подключаемые библиотеки (DLL – dynamic link libraries) представляют собой важное средство операционной системы ОС Windows. DLL – библиотеки позволяют подключать предварительно созданные модули к операционной системе, что обеспечивает для приложений общий код, создает модульное представление часто используемых функций и способствует расширяемости. ОС Windows сама состоит, в основном, из DLL-библиотек. Любое приложение, где применяется Win32API, использует функциональные возможности DLL. Использование динамических библиотек это способ осуществления модульности в период выполнения программы. DLL позволяет упростить и саму разработку программного обеспечения. Вместо того чтобы каждый раз перекомпилировать огромные ЕХЕ-программы, достаточно перекомпилировать лишь отдельный динамический модуль. Кроме того, доступ к динамической библиотеке возможен сразу из нескольких исполняемых модулей, что делает многозначность более гибкой. Структура DLL-модуля практически такая же, как и ЕХЕ-модуля. Динамическая библиотека это еще и возможность разработки приложений на разных языках. Динамическая библиотека, написанная, скажем, на Visual C++, может вызываться из программ, написанных на любых языках. Следует также отметить, что использование динамических библиотек экономит дисковое пространство, т. к. процедура из такой библиотеки помещается в модуль лишь один раз, в отличие от процедур, помещаемых в модули из статических библиотек.

Динамическая библиотека проецируется на адресное пространство вызывающего процесса. В результате она становится частью этого процесса. Если динамическая библиотека резервирует динамическую память, то этот блок памяти принадлежит процессу. При удалении библиотеки из памяти блок остается и удаляется только процессом.

При создании DLL необходимо указывать экспортируемые функции. Делается это следующим образом [7]:

_declspec(dllexport)int Func(char * s);

В программе, вызывающей эту функцию, следует ввести следующую строку:

_declspec(dllimport) int Func(char * s);

Для дальнейшего изучения DLL введем понятие связывание. Во время трансляции связываются имена, указанные в программе как внешние с соответствующими именами из библиотек. Такое связывание называется ранним (или статическим). Напротив, в случае с динамической библиотекой связывание происходит во время выполнения модуля. Такое связывание называется поздним (или динамическим). При этом позднее связывание может происходить в автоматическом режиме в начале запуска программы и при помощи специальных API-функций (см. ниже) по желанию программиста. При этом говорят о явном и неявном связывании (рис.1.2).

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

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

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

BOOL DLLEntryPoint(HINSTANCE hInstDLL, DWORD dwNotification,

LPVOID lpReserved)

Имя функции DLLEntryPoint() служит просто заполнителем. По умолчанию модуль подключения ищет функцию с именем DLLMain(). При определении точки входа в DLL функции можно присвоить любое имя. При вызове процедуры входа в нее помещаются три параметра:

  • идентификатор DLL-модуля;

  • причина вызова;

  • резерв.

Рассмотрим подробнее второй параметр процедуры ввода, который может принимать четыре возможных значения.

  • DLL_PROCESS_ATTACH - Сообщает, что динамическая библиотека загружена в адресное пространство вызывающего процесса.

  • DLL_THREAD_ATTACH - Сообщает, что текущий процесс создает новый поток. Такое сообщение посылается всем динамическим библиотекам, загруженным к этому времени процессом.

  • DLL_PROCESS_DETACH - Сообщает, что динамическая библиотека выгружается из адресного пространства процесса.

  • DLL_THREAD_DETACH - Сообщает, что некий поток, созданный данным процессом, в адресное пространство которого загружена данная динамическая библиотека, уничтожается.