МІНІСТЕРСТВО ОСВІТИ І НАУКИ, МОЛОДІ ТА СПОРТУ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”
Кафедра ЕОМ
ЗВІТ
до лабораторної роботи №7
з курсу “ Системне програмування ”
“ СТВОРЕННЯ БІБЛІОТЕК ДИНАМІЧНОГО КОМПОНУВАННЯ ТА ЇХ ВИКОРИСТАННЯ В РЕЖИМІ ЯВНОГО ЗВ’ЯЗУВАННЯ ”
Львів 2012
МЕТА
Ознайомитись з технологією створення та використання бібліотек динамічного компонування з використанням явного зв’язування.
Ввести два рядки тексту та ціле число N, порівняти між собою перші N символів в рядках, ігноруючи пробіли.
ТЕОРЕТИЧНІ ВІДОМОСТІ
DLL (англ. Dynamic-link library — динамічно завантажувана бібліотека) — реалізовані компанією Microsoft загальні бібліотеки в ОС Windows. Як правило бібліотеки мають розширення файлу *.dll, *.ocx (для бібліотек, що містять елементи керування ActiveX) або *.drv (драйвери старих версій ОС). Структура DLL така сама, як і в PE-файлів (Portable Executable) для 32-, 64-розрядних Windows, та New-Executable (NE) для 16-бітових Windows.
DLL може містити 2 типи функцій: експортні та внутрішні. Експортні функції визначаються за допомогою ключового слова __declspec(dllexport) і можуть бути викликані з програм, що завантажили динамічну бібліотеку, яка містить ці функції. Внутрішні функції – це функції, які використовуються в середині DLL і не можуть бути викликані ззовні.
DLL є модулем (module). Тобто, вона складається з: сегментів коду, сегментів ресурсів та одного сегменту даних. Крім цього DLL може містити точку входу. Точка входу – це функція DllMain, яка викликається при завантаженні або вивантажені бібліотеки потоком або процесом. Ця функція має наступний прототип:
BOOL APIENTRY DllMain(
HANDLE hModule, // Хендл DLL модуля
DWORD ul_reason_for_call, // Причина виклику
LPVOID lpReserved ); // Зарезервовано
Якщо DllMain повертає FALSE, то бібліотека вважається такою, що не завантажилася. При неявному зв’язуванні це призведе до відмови запуску програми, а при явному – помилки завантаження лише цієї бібліотеки.
В процесі виконання вміст бібліотеки залишається незмінним (сегменти коду та сегменти ресурсів), що дозволяє завантажувати її в пам’ять в єдиному екземплярі і використовувати багатьма завданнями одночасно. Використання dll дозволяє економити пам’ять, забезпечити модульність програм, полегшити процес встановлення програм.
Можливі 2 способи використання динамічних бібліотек. Вони називаються явним та неявним зв’язуванням. Явне та неявне зв’язування бібліотеки з програмою мають суттєві відмінності в процесі написання та компіляції програми.
Явне зв’язування бібліотеки з програмою (Run-time dynamic linking) полягає в тому, що бібліотека (яка міститься у файлі з розширенням .dll) завантажується в пам’ять в момент виклику АРІ функції LoadLibrary або LoadLibraryEX програмою. При успішному виконанні функція повертає адресу точки входу. При відсутності бібліотеки, яку необхідно завантажити, або при помилках її завантаження функція поверне NULL, а сама програма продовжить виконання. Для виклику бібліотечної функції необхідно оголосити вказівник на функцію, та присвоїти йому адресу бібліотечної функції. Для цього необхідно використати АРІ функцію GetProcAddress, яка повертає адресу вказаної їй у параметрі бібліотечної функції. По завершенню роботи програми необхідно вивантажити бібліотек за допомогою функції FreeLibrary.
Для успішної компіляції необхідно мати лише dll файл бібліотеки. Запуск програми відбудеться навіть за відсутності бібліотечного файлу, оскільки його наявність при використанні явного зв’язування не перевіряється.
Хід роботи
1. Використовуємо створену бібліотеку на попередній лабораторній роботі lab6dll .
2. На другому етапі створюємо новий проект типу Win32 Project та в налаштуваннях вибираємо тип проекту Console Application. Явним зв’язуванням підключаємо бібліотеку створену на попередній лабораторній роботі.
3. Пишемо програму в стилі С/С++, яка здійснюватиме виклик функцій з бібліотеки. Компілюємо і запускаємо програму
КОДИ ПРОГРАМ
maindll.h
#ifndef _maindll_h_
#define _maindll_h_
#include <stdio.h>
#include <windows.h>
using namespace System;
extern "C" __declspec(dllexport) void CmpStrN(char* str1,char* str2,int N);
#endif
maindll.cpp
#include "maindll.h"
using namespace System;
extern "C" __declspec(dllexport) void CmpStrN(char* str1,char* str2,int N)
{
String^ str11=System::Runtime::InteropServices::Marshal::PtrToStringAnsi((IntPtr)str1);
String^ str12=System::Runtime::InteropServices::Marshal::PtrToStringAnsi((IntPtr)str2);
int index=0;
int err=0;
int i=0;
int j=0;
while(index<N){
if(str11[i] == ' ') i++;
if(str12[j] == ' ') j++;
if(str11[i] == str12[j]){
index++;
i++;
j++;
}
else{
index++;
i++;
j++;
err++;
}
}
if(err == 0) Console::WriteLine(N.ToString()+" - this string is similar!");
else Console::WriteLine(N.ToString()+" - this string is not similar!");
}
maintest.cpp
#include <conio.h>
#include "maindll.h"
#include <vcclr.h>
#include <stdio.h>
#include <Windows.h>
using namespace System;
void main()
{
HMODULE hlib;
hlib = LoadLibrary(L"lab6dll.dll");
void (*CmpStrN)(char*, char*, int);
(FARPROC &)CmpStrN = GetProcAddress(hlib, "CmpStrN");
String^ string1;
String^ string2;
String^ N;
Console::WriteLine("Enter first string:");
string1 = Console::ReadLine();
Console::WriteLine("Enter second string:");
string2 = Console::ReadLine();
Console::WriteLine("Enter 'N' for check:");
N = Console::ReadLine();
pin_ptr<const wchar_t> wch = PtrToStringChars(string1);
size_t string1size = wcslen(wch) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
char str1[newsize];
wcstombs_s(&convertedChars, str1, string1size, wch, _TRUNCATE);
strcat_s(str1, " (char *)");
pin_ptr<const wchar_t> wch1 = PtrToStringChars(string2);
size_t string2size = wcslen(wch1) + 1;
const size_t newsize1 = 100;
size_t convertedChars1 = 0;
char str2[newsize1];
wcstombs_s(&convertedChars1, str2, string2size, wch1, _TRUNCATE);
strcat_s(str2, " (char *)");
__int32 iN = System::Int32::Parse(N);
Console::WriteLine("Result:");
CmpStrN(str1,str2,iN);
FreeLibrary(hlib);
_getch();
}
РЕЗУЛЬТАТ ВИКОНАННЯ ПРОГРАМИ
Рис. 1. Рядки одинакові
Рис. 2. Рядки не є однаковими
ВИСНОВОК: На даній лабораторній роботі я ознайомився з технологією створення та використання бібліотек динамічного компонування з використанням явного зв’язування.