Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
шпоры по Леонову, 5семестр.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
503.3 Кб
Скачать

39. Библиотеки динамической компоновки. Явная и неявная загрузка dll.

В среде MS-DOS все объектные модули программы связываются статически на стадии компоновки. Windows разрешает динамическое связывание, т.е. загрузку и подключение к программе в период выполнения специальных библиотек. Одной и той же динамически подключаемой библиотекой (Dynamic-Link Library, DLL) могут воспользоваться сразу несколько программ, что экономит память и дисковое пространство. Кроме того динамические подключения позволяют увеличить модульность программ, поскольку DLL-модули компилируются и тестируются раздельно.

Изначально DLL-биб. разрабатывались в расчете на язык C. Классы каркаса можно статически или динамически подключать к нашему приложению. DLL обеспечивает модульность программы в период ее разработки. В Windows поддержка основных фу-ций строится на применении DLL.

В DLL содержатся так называемые экспортируемые (exported) фу-ции , которые импортирует (import) клиентская программа (программа, загружающая DLL). В Win32 DLL позволяют экпортировать и глобальные переменные.

DLL инициализируется функцией DllMain

Согласование экспортируемых элементов с импортируемыми

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

В коде DLL экп. фу-ции надо объявлять явным образом:

_ _declspec(dllexport) int MyFunction (int n);

В клиет. программе необх. указ., что данная фу-ция импортирется:

_ _ declspec(dllimport) int MyFunction (int n);

Компилятор С++ сгенерирует для MyFunction так наз. расширенное имя ,кот. нельзя использовать в других языках. Чтобы у фу-ции было простое имя, например MyFunction, объявления фу-ции следует писать так:

extern “C” _ _ declspec(dllexport) int MyFunction (int n);

extern “C” _ _ declspec(dllimport) int MyFunction (int n);

Одних только объявлений импортируемых объектов недостаточно, чтобы клиент установил связь с DLL.В проекте клиентской программы надо определить библиотеку импорта (LIB) для компоновщика, а сама программа должна содержать как минимум один явный вызов какой-то фу-ции, импортируемой из DLL.

Явное и неявное связывание (загрузка dll)

Неявное связывание.

Формируя DLL, компоновщик создает дополнит. LIB-файл - это суррогат DLL, добавляемы й к проекту клиетской программы. Когда собирается клиетская программа, импортируемые символьные имена согласуются с экспортируемыми из LIB, и эти имена (или пор. номера) сохр. в EXE-файле.LIB-файл содер. и имя DLL-файла (без указания пути), кот. тоже хран. в EXE-файле. При загрузке клиента Windows находит и загружает нужные DLL-модули, а затем динамически связывает их по символьным именам или пор. номерам.

Явное связывание.

При явном связывании файл импорта не используется – вместо этого вызывается Win32 фу-ция LoadLibrary, указывая полное имя DLL как параметр. LoadLibrary возвращает параметр типа HINSTANCE, который можно использовать в вызове GetProcAddress, преобразующий символьное имя (или пор. номер) в адрес. Допустим, что DLL экпортирует фу-цию так:

extern “C” _ _declspec(dllexport) double SquareRoot(double d);

Пример явного связывания клиента с экпортируемой фу-цией:

Typedef double (SQRTPROC) (double);

HISTANCE hInstance;

SQRTPROC* pFunction;

VERIFY (hInstance = ::LoadLibrary(“c:\\winnt\\system\\mydll.dll”));

VERIFY (pFunction= (SQRTPROC*)::GetProcAddress((HMODULE) hInstance, “SquareRoot” ));

Double d= (* pFunction)(81.0): // вызов функции из DLL

Если при явном связывании можно определить, когда загружать или выгружать DLL, то при неявном связывании все DLL загружаются в момент загрузки клента. Явное связывание позволяет указывать и то, какие DLL следует загрузить. Например, пусть есть одна DLL со строковыми ресурсами на англ. языке, а другая - со строковыми ресурсами на русском. Когда пользователь выберет язык для работы, ваше приложение сможет загрузить соответствующую DLL.

Если мы компонуем программу явным образом, с исп. LoadLibrary , то можно указывать полное имя DLL (с определ. пути ). Если же полный путь не указан, или при неявной компоновке Windows будет искать вашу DLL в след. порядке:

1. В каталоге, содер. данный EXE-файл 2. В текущем кат. процесса

3. В системном кат. Windows 4. В кат. Windows

Основываясь на каркасе MFS-приложений мы можем создавать2 вида DLL с поддержкой MFS-биб. : DLL-расширения и обычные DLL.

DLL-расширение (поддерживает интерфейс С++) может экпортировать целые классы, а клиент может создавать объекты этих классов.

Если нам нужна DLL, которую можно загружать в любую Win32 –среду программирования, то здесь исп. обычная DLL.Обычная DLL может экспортировать только С-фу-ции и не способна эксп. С++ классы.

Общие DLL MFC-библиотеки.

mfc42d.dll важнейшие MFC-классы (ядро);

mfco42d.dll ActiveX –(OLE) классы;

mfcd42d.dll классы для работы с базами данных(ODBC и DAO)

mfcn42d.dll классы WinSock, WinInet

DDL с пользовательскими элементами управления

DLL используют для хранения пользоват. эл. управ.Для этих эл. более подходит обычная DLL.

Пол. эл. упр. аналогичен обычному (вроде поля ввода) в том плане, что тоже посылает родит. Окну уведомляющие сообщения WM_COMMAND и получает сообщения, орпед. пользователем.

В оконном классе пользоват. эл. упр. сущ. фу-ция WndProc, кот. принимает сообщения, посланные окнам данного класса. Эта фу-ция раположена в DLL. При инциализации DLL (вызовом DllMain) DLL может вызвать для элемента управ. фу-цию RegisterClass. Поскольку DLL является частью процесса, клиентская программа получает возможность создавать дочерние окна класса пользовательского эл.упр-ия. Клиент знает имя оконного класса элемента упр-ия и он использует это имя при создании дочернего окна. Весь код эл. уп-ия, включая WndProc , находится в DLL. Нужно только, чтобы клиент загружал DLL до создания дочернего окна.