Лабораторная работа

Создание и использование DLL в C++

Категория:

Лабораторная работа

Дисциплина:

Системное программирование

Город:

Беларусь, Минск

Учебное заведение:

БНТУ, ФИТР

Стоимость работы:

5 руб.

Оценка: 10
Объем страниц: 11
Год сдачи: 2021
Дата публикации: 10.02.2021

* Кроме файла с работой, также есть архив с дополнительными файлами.

Описание дополнительных файлов:

Папка LW-3 — содержит исходный код программы на языке C++

Фрагменты для ознакомления

Лабораторная работа № 3

СОЗДАНИЕ И ИСПОЛЬЗОВАНИЕ DLL

 

Цель работы: рассмотреть ряд аспектов создания и использования динамических библиотек DLL в операционной среде Win32.

Изучаемые вопросы:

1. Функция DllMain. Последовательность вызовов в многопоточном приложении. Назначение и классификация диалоговых окон. 

2. Экспорт/импорт функций. 

3. Экспорт/импорт ресурсов.

4. Согласование интерфейсов. 

5. Загрузка неявно подключаемой DLL. 

6. Динамическая загрузка и выгрузка DLL. 

7. Вызов функции по номеру.

8. Список динамических библиотек процесса.

 

Постановка задачи:

Разработать многопоточное Win32-приложение и двe DLL-библиотеки, одна из которых загружается явно, а вторая неявно. Первая динамическая библиотека содержит код обработки информации (например, код доступа к системной информации файловых систем FAT или NTFS), вторая – ресурсы типа диалог. Индивидуальное задание получить у преподавателя. 

 

4.1. Функция DllMain. Последовательность вызовов в многопоточном приложении. Назначение и классификация диалоговых окон

Код библиотеки времени выполнения языка C++ вызывает функцию DllMain каждый раз, когда процесс или поток подключается к DLL или отключается от DLL (загрузке и выгрузке DLL‑библиотеки).

Примерный код данной функции может быть таким:

_declspec(dllexport) int counterCalledDLLMAin = 0;    // экспортируемый счётчик вызовов

BOOL WINAPI DllMain(HMODULE hModule,    // дескриптор модуля DLL
       DWORD ul_reason_for_call,         // причина вызова DllMain()
       LPVOID lpvReserved)        // указатель, зарезервированный для использования Windows
{
       TCHAR szBuf[100] = { 0 };
       
       switch (ul_reason_for_call)
       {
             case DLL_PROCESS_ATTACH:
             {//выполнить в процессе инициализацию, необходимую ее функциям     
                    counterCalledDLLMAin++;
                    _stprintf_s(szBuf, TEXT("DLLInformationMemory - Информация(Counter=%i)"), counterCalledDLLMAin);
                    MessageBox(NULL, TEXT("Новый процесс пытается получить доступ к DLL. DLL спроецирована на адресное пространство процесса"), szBuf, MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);             
                    break;
             }
             case DLL_THREAD_ATTACH:
             {
                    counterCalledDLLMAin++;
                    _stprintf_s(szBuf, TEXT("DLLInformationMemory - Информация(Counter=%i)"), counterCalledDLLMAin);
                    MessageBox(NULL, TEXT("Новый поток существующего процесса пытается получить доступ к DLL"), szBuf, MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
                    break;
             }
             case DLL_PROCESS_DETACH:
             {      // очистку в данном процессе
                    counterCalledDLLMAin++;
                    _stprintf_s(szBuf, TEXT("DLLInformationMemory - Информация(Counter=%i)"), counterCalledDLLMAin);
                    MessageBox(NULL, TEXT("Последний поток процесса отсоединяется от DLL"), szBuf, MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
                    break;
             }
             case DLL_THREAD_DETACH:
             {
                    counterCalledDLLMAin++;
                    _stprintf_s(szBuf, TEXT("DLLInformationMemory - Информация(Counter=%i)"), counterCalledDLLMAin);
                    MessageBox(NULL, TEXT("Один из потоков процесса отсоединяется от DLL"), szBuf, MB_OK | MB_ICONINFORMATION | MB_APPLMODAL);
                    break;
             }
       }
       return TRUE;        // корректно ли прошла инициализация DLL
}

Причины вызова DllMain определяется параметром ul_reason_for_call. При первой загрузке библиотеки DLL процессом вызывается функция DllMain с ul_reason_for_call, равным DLL_PROCESS_ATTACH. Каждый раз при создании процессом нового потока DllMain вызывается с ul_reason_for_call, равным DLL_THREAD_ATTACH.

По окончании работы процесса с DLL функция DllMain вызывается с параметром ul_reason_for_call, равным DLL_PROCESS_DETACH. При уничтожении потока (кроме первого) ul_reason_for_call будет равен DLL_THREAD_DETACH.

 

4.2. Экспорт/импорт функций

Есть два способа загрузки Dll-функции:

1. При неявном связывании DLL библиотеки:

Код функции из DLL библиотеки (откуда будет экспортирована функция):

#define DLLEXPORTM _declspec(dllexport)
DLLEXPORTM VOID CALLBACK getGlobalMemoryStatus(HWND hDlg, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
VOID CALLBACK getGlobalMemoryStatus(HWND hDlg, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)

 

Код импортирования из DLL библиотеки функции getGlobalMemoryStatus():

#define DLLIMPORTM __declspec(dllimport)
DLLIMPORTM VOID CALLBACK getGlobalMemoryStatus(HWND hDlg, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
IDTimer = SetTimer(hDlg, IDC_TIMER1, NELAPSE, (TIMERPROC)getGlobalMemoryStatus);
SendMessage(hDlg, WM_TIMER, NULL, NULL);

 

2. При явном связывании DLL библиотеки:

Содержимое файла Source.def из DLL библиотеки:

LIBRARY "NewDllexplicit"
EXPORTS
hIcon  @2
gProtect @1

 

Загрузка функции может быть выполнена следующим образом:

typedef VOID (PFN)(DWORD protect, TCHAR(&szBuf)[100]);

       static HMODULE hModule = NULL;
static PFN* function;


hModule = LoadLibrary(TEXT("NewDllexplicit"));
             if (hModule)
             {
                    function = (PFN*)GetProcAddress(hModule, (LPCSTR)MAKEINTRESOURCE(1));
                    if (function == NULL)
                    {
                           MessageBox(hDlg, _TEXT("Функция gProtect не найдена"),       TEXT("LoadLibrary"), MB_OK | MB_ICONQUESTION);
                           DestroyWindow(hDlg);
                           return 0;
                    }
             }
             else
             {
                    MessageBox(hDlg, _TEXT("Библиотека не найдена"), _TEXT("LoadLibrary"), MB_OK | MB_ICONQUESTION);
                    DestroyWindow(hDlg);
                    return 0;
       }

FreeLibrary(hModule);

 

4.3. Экспорт/импорт ресурсов.

4.4. Согласование интерфейсов.

4.5. Загрузка неявно подключаемой DLL.

4.6. Динамическая загрузка и выгрузка DLL.

4.7. Вызов функции по номеру.

4.8. Список динамических библиотек процесса.

 

Результаты работы программного обеспечения:

79