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

15. Понятие динамически-загружаемой библиотеки. Создание dll-библиотеки. Использование dll-библиотеки в программе методом динамический импорта процедур.

1 И 2 часть вопроса смотри в вопросе номер 14

DLL представляет собой дополняемый модуль ОС (обычно DLL), код и ресурсы которого могут использоваться в составе других динамических библиотек и приложений. DLL – программа с множеством точек входа. В отличие от статической библиотеки, которая включается в выполняемый exe модуль на этапе сборки, динамическая библиотека собирается в виде отдельно выполняемого модуля. Использование динамической библиотеки выполняется одним из двух способов:

  • Статического импорта

  • Динамического импорта

Для создания DLL в разных языках используются разные средства. В C++:

Создание:

Динамический импорт. Если при статическом импорте загрузку DLL в память обеспечивает ОС, то при динамическом импорте это делает программист вручную. Загрузить DLL можно с помощью функции:

HANDLE LoadLibrary(LPCSTR libFileName)

Загрузка DLL-библиотеки в память:

HMODULE LoadLibrary(LPCTSTR lpFileName);

HMODULE LoadLibraryEx(LPCTSTR lpFileName, _Reserved_  HANDLE hFile, DWORD dwFlags);

HMODULE GetModuleHandle(LPCTSTR lpModuleName); GetModuleHandleEx.

DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename, DWORD nSize);

Освобождение DLL-библиотеки:

bool FreeLibrary(HMODULE hModule); FreeLibraryAndExitThread.

Получение адреса функции в DLL-библиотеке:

void* GetProcAddress(HMODULE hModule, LPCSTR lpProcName);

Применение:

typedef int TMin(int x, int y); // добавить __stdcall

TMin* pMin;

pMin = (TMin*)GetProcAddress(hModule, "_Min@8");

int a = pMin(10, 20);

16. Понятие динамически-загружаемой библиотеки. Создание в DLL-библиотеке разделяемых между приложениями глобальных данных. Разделы импорта и экспорта DLL-библиотеки. Переадресация вызовов процедур DLL-библиотек к другим DLL-библиотекам. Исключение конфликта версий DLL.

DLL представляет собой дополняемый модуль ОС (обычно DLL), код и ресурсы которого могут использоваться в составе других динамических библиотек и приложений. DLL – программа с множеством точек входа. В отличие от статической библиотеки, которая включается в выполняемый exe модуль на этапе сборки, динамическая библиотека собирается в виде отдельно выполняемого модуля. Использование динамической библиотеки выполняется одним из двух способов:

  • Статического импорта

  • Динамического импорта

Разделяемые данные – shared data:

#pragma section("mysection", read, write, shared)

__declspec(allocate("mysection")) int Number = 0;

Экспорт

Если модификатор __declspec(dllexport) указан перед переменной, прототипом функции или C++классом, компилятор Microsoft С/С++ встраивает в конечный OBJфайл дополнительную информацию. Она понадобится компоновщику при сборке DLL из OBJфайлов.

Обнаружив такую информацию, компоновщик создает LIB-файл со списком идеyтификаторов, экспортируемых из DLL. Этот LIB􏰀файл нужен при сборке любого EXE-модуля, ссылающегося на такие идентификаторы. Компоновщик также вставляет в конечный DLL-файл таблицу экспортируемых идентификаторов — раздел экспорта, в котором содержится список (в алфавитном порядке) идентификаторов экспортируемых функций, переменных и классов. Туда же помещается относительный виртуальный адрес (relative virtual address, RVA) каждого идентификатора внутри DLL-модуля.

Воспользовавшись утилитой DumpBin.exe (с ключом -exports) из состава Microsoft Visual Studio, мы можем увидеть содержимое раздела экспорта в DLL-модуле.

Импорт

Разрешая ссылки на импортируемые идентификаторы, компоновщик создает в конечном EXE-модуле раздел импорта (imports section). В нем перечисляются DLL, необходимые этому модулю, и идентификаторы, на которые есть ссылки из всех используемых DLL.

Воспользовавшись утилитой DumpBin.exe (с ключом -imports), мы можем увидеть содержимое раздела импорта.

Запись о переадресации вызова функции (function forwarder) — это строка в разделе экспорта DLL, которая перенаправляет вызов к другой функции, находящейся в дру􏰀 гой DLL. Например, запустив утилиту DumpBin из Visual C++ для Kernel32.dll в Win􏰀 dows 2000,

   Здесь есть четыре переадресованные функции. Всякий раз, когда Ваше приложе􏰀ние вызывает HeapAlloc, HeapFree, HeapReAlloc или HeapSize, его EXE􏰀модуль динами􏰀 чески связывается с Kernel32.dll. При запуске EXE􏰀модуля загрузчик загружает Ker􏰀 nel32.dll и, обнаружив, что переадресуемые функции на самом деле находятся в NTDLL.dll, загружает и эту DLL. Обращаясь к HeapAlloc, программа фактически вызы􏰀 вает функцию RtlAllocateHeap из NTDLL.dll. А функции HeapAlloc вообще нет!

При вызове HeapAlloc (см. ниже) функция GetProcAddress просмотрит раздел экс􏰀 порта Kernel32.dll и, выяснив, что HeapAlloc — переадресуемая функция, рекурсивно вызовет сама себя для поиска RtlAllocateHeap в разделе экспорта NTDLL.dll. GetProcAddress(GetModuleHandle("Kernel32"), "HeapAlloc");  

Вы тоже можете применять переадресацию вызовов функций в своих DLL. Самый

простой способ — воспользоваться директивой pragma: // переадресация к функции из DllWork

#pragma comment(linker, "/export:SomeFunc=DllWork.SomeOtherFunc")

Эта директива сообщает компоновщику, что DLL должна экспортировать функцию SomeFunc, которая на самом деле реализована как функция SomeOtherFunc в модуле DllWork.dll. Такая запись нужна для каждой переадресуемой функции.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]