МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
Дніпропетровський національний університет залізничного транспорту імені академіка В. Лазаряна
Лабораторна робота №6
з предмету: «Операційні системи»
на тему: «Динамічні бібліотеки (DLL)»
2015
Мета роботи:
- ознайомитися з поняттям DLL;
- вивчити способи створення DLL і варіанти роботи з ними;
- отримати практичні навики створення і використання динамічних бібліотек.
Теоретичні відомості
Створення власної DLL З точки зору програміста - DLL є бібліотекою функцій (ресурсів), якими може користуватися будь-який процес, що завантажив цю бібліотеку. Саме завантаження, до речі, віднімає час і збільшує витрату споживаної додатком пам'яті; тому бездумне дроблення одного застосування на безліч DLL нічого хорошого не принесе.
Інша справа - якщо якісь функції використовуються декількома застосуваннями. Тоді, помістивши їх в одну DLL, ми позбавимося від дублювання коди і скоротимо загальний об'єм додатків - і на диску, і в оперативній пам'яті. Можна виносити в DLL і рідко використовуваних функціях окремого застосування;
Процесу, що завантажив, DLL доступні не всі її функції, а що лише явно надаються самій DLL для "зовнішнього світу" - т.з. що експортуються . Функції, призначені суто для "внутрішнього" користування, експортувати безглуздо (хоча і не заборонено). Чим більше функцій експортує DLL - тим повільніше вона завантажується; тому до проектування інтерфейсу (способу взаємодії DLL із зухвалим кодом) слід віднестися уважніше. Хороший інтерфейс інтуїтивно зрозумілий програмістові, небагатослівний і елегантний: як говориться, ні додати, ні відняти. Строгих рекомендацій із цього приводу дати неможливо - уміння приходить з досвідом.
Для експортування функції з DLL - перед її описом слід вказати ключове слово __ declspec(dllexport).
Виклик функції із DLL.
Існує два способи завантаження DLL: з явною і неявною компоновкою. При неявній компоновці функції завантажуваними DLL додаються в секцію імпорту викликаючого файлу. При запуску такого файлу завантажувач операційної системи аналізує секцію імпорту і підключає всі вказані бібліотеки.
Явна компоновка устраняет всі ці недоліки - ціною деякого ускладнення коди. Програмістові самому доведеться поклопотатися про завантаження DLL і підключенні функцій, що експортуються (не забуваючи при цьому про контроль над помилками, інакше в один прекрасний момент справа кінчиться зависанням системи). Зате явна компоновка дозволяє підвантажувати DLL в міру необхідності і дає програмістові можливість самостійно обробляти ситуації з відсутністю DLL. Можна піти і далі - не задавати ім'я DLL в програмі явно, а сканувати такий-то каталог на предмет наявності динамічних бібліотек і підключати всі знайдені до додатка. Саме так працює механізм підтримки plug-in’ов в популярному файлі-менеджерові FAR (та і не тільки в нім).
Таким чином, неявною компоновкою доцільно користуватися лише для підключення завантажуваних в кожному сеансі, життєво необхідних для роботи додатка динамічних бібліотек; у всіх останніх випадках - переважно явна компоновка.
Загрузка DLL з неявною компоновкою
Щоб викликати функцію з DLL, її необхідно оголосити в зухвалому коді - або як external (тобто як звичайну зовнішню функцію), або передувати ключовим словом __declspec(dllimport). Перший спосіб популярніший, але другий все ж переважно - в цьому випадку компілятор, зрозумівши, що функція викликається саме з DLL, зможе відповідним чином оптимізувати код.
Загрузка DLL з явною компоновкою
Явне завантаження динамічних бібліотек здійснює функція HINSTANCE Loadlibrary(LPCTSTR lplibfilename) або її розширений аналог HINSTANCE Loadlibraryex(LPCTSTR lplibfilename, HANDLE hfile, DWORD dwflags).
Обидві вони експортуються з Kernel32.DLL, отже, кожне застосування вимагає неявної компоновки принаймні цієї бібліотеки. В разі успішного завантаження DLL повертається лінійна адреса бібліотеки в пам'яті.
Передавши його функції FARPROC Getprocaddress(HMODULE hmodule, LPCSTR lpprocname) - ми отримаємо покажчик на функцію lpprocname, що експортується даною DLL. При виникненні помилки обидві функції повертають NULL. Після завершення роботи з динамічною бібліотекою її слід звільнити викликом функції BOOL Freelibrary(HMODULE hlibmodule).
Текст программи:
Func.cpp
#include "stdafx.h"
#include "func.h"
using namespace std;
extern "C" _declspec(dllexport) int factorial (int a)
{
int sum=1;
while (a>2)
{
sum*=a;
a--;
}
sum*=2;
return sum;
};
extern "C" _declspec(dllexport) void out (char *buf)
{
cout<<"\nYou've just wrote:\n"<<buf;
};
Func.h
extern "C" __declspec(dllexport) int factorial (int a);
extern "C" __declspec(dllexport) void out (char *buf);
Not.cpp
#include "stdafx.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
bool fl=true;
while (fl)
{
cout<<"\n1. Func 1"<<"\n2. Func 2\n"<<"0. Exit\n";
int v;
cin>>v;
switch (v)
{
case 1:
{
cout<<"\nVvedite chislo\n";
int a;
cin>>a;
cout<<"\nFactorial raven "<<factorial(a);
};
break;
case 2:
{
cout<<"\nVvedite stroku\n";
char buf[100],h;
cin.get(h);
cin.get(buf,100);
out(buf);
};
break;
case 0:
fl=false;
break;
}
}
return 0;
}
Func.h (в Not)
extern "C" __declspec(dllexport) void out (char *buf);
extern "C" __declspec(dllexport) int factorial (int a);
Yes.cpp
// Yes.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
using namespace std;
typedef int (__cdecl *func1)(int a);
typedef void (__cdecl *func2)(char* buf);
int _tmain(int argc, _TCHAR* argv[])
{
HINSTANCE Dll=LoadLibrary("DLL.dll");
func1 factorial = (func1)GetProcAddress(Dll, "factorial");
func2 out = (func2)GetProcAddress(Dll, "out");
bool fl=true;
while (fl)
{
cout<<"\n1. Func 1"<<"\n2. Func 2\n"<<"0. Exit\n";
int v;
cin>>v;
switch (v)
{
case 1:
{
cout<<"\nVvedite chislo\n";
int a;
cin>>a;
cout<<"\nFactorial raven "<<factorial(a);
};
break;
case 2:
{
cout<<"\nVvedite stroku\n";
char buf[100],h;
cin.get(h);
cin.get(buf,100);
out(buf);
};
break;
case 0:
fl=false;
break;
}
}
return 0;
}
Func.h (в Yes)
extern "C" __declspec(dllexport) void out (char *buf);
extern "C" __declspec(dllexport) int factorial (int a);
Результаты роботи прогами:
/
Висновок: під час виконання даної лабораторної роботи ознайомилася з поняттям DLL, вивчила способи створення DLL і варіанти роботи з ними, отримала практичні навики створення і використання динамічних бібліотек.