DLL библиотеки

Автор работы: Пользователь скрыл имя, 24 Мая 2013 в 21:12, дипломная работа

Краткое описание

Найчастіше проект підключається до DLL статично, або неявно, на етапі компонування. Завантаженням DLL при виконанні програми управляє операційна система. Однак, DLL можна завантажити і явно, або динамічно, в ході роботи додатку.
Мета дипломної роботи розробити самостійно декілька власних DLL бібліотек у середовищі Delphi7, та показати приклади роботи з ними.

Содержание

Вступ 4
1.Огляд відомих рішень 6
2. Вибір метода рішення 11
2.1 Постановка задачі 11
2.2 Обраний метод 11
3. Реалізація 21
4.Охорона праці 26
4.1 Характеристика приміщення 26
4.2 Дослідження природного освітлення 29
4.3 Дослідження штучного освітлення 33
4.4 Дослідження достатності вентиляції 35
4.5 Дослідження пожежобезпеки 38
Список Літератури 40

Прикрепленные файлы: 1 файл

Звіт на Дипломну(ап).doc

— 456.00 Кб (Скачать документ)

Крім цих можливостей, існує й інший спосіб, а саме: послідовність занесення в стек параметрів методу. Припустимо, є метод, який використовує для роботи два параметри:

procedure DoSomething(N:integer; D:TDateTime);


Зазначений спосіб полягає  в тому, що спочатку в стек може бути поміщена константа N, а потім D (зліва направо) або спочатку поміщається константа D, а потім N (справа наліво). Крім того, деякі мови програмування (зокрема, Delphi) частину параметрів методу взагалі не поміщають в стек, а передають їх через регістри процесора. До того ж у різних мовах програмування параметри можуть міститися в стек як зліва направо, так і справа наліво. Якщо вони були поміщені зліва направо, а викликуваний метод буде читати справа наліво, то вийде плутанина: як значення константи N викликуваний метод буде вважати значення правої половини константи D, а константу D він буде формувати з константи N і лівої половини D.

З цієї причини в будь-якій мові програмування передбачена можливість оголосити, який з методів - викликуваний або викликаючий,  буде очищати стек і в якій послідовності параметри методу поміщаються в стек. Таке оголошення називається угодою виклику (calling conversion); є ряд зарезервованих слів, які поміщаються після заголовка методів, як показано в таблиці.

Директива

Порядок слідування параметрів

Очистка стека

Використанна регістрів 

register

Зліва направо

викликуваний метод

+

pascal

Зліва направо

викликуваний метод

-

cdecl

Зліва направо

викликуваний метод

-

stdcall

Зліва направо

викликуваний метод

-

safecall

Зліва направо

викликуваний метод

-


 

Для методів, що експонуються в DLL, рекомендується (але не обов'язково) використовувати угоду виклику, що і в Windows API. Для 32-розрядних додатків Windows API методи реалізовані таким чином, що параметри поміщаються в стек справа наліво і стек очищає викликуваний метод; при цьому не використовуються регістри процесора для передачі даних. Цим умовам задовольняє директива stdcall, яка в описаному вище прикладі поміщається після заголовка методу AddOne. Якщо після заголовка методу відсутня угода про виклик, то за замовчуванням Delphi використовує угоду register.

Однак написаного вище коду ще недостатньо для виклику методу AddOne з іншого модуля. Одна DLL може надавати декілька методів зовнішньому модулю. Для того щоб зовнішній модуль міг вибрати конкретний метод, в DLL повинна бути присутня спеціальна секція, яка має заголовок exports. У нашому прикладі цю секцію можна оголосити таким чином:

exports

  AddOne index 1 name ’CalculateSum’;


 

Для експонування методу в секції exports наводиться його назва (AddOne), після якого слідує або службове слово index з цілочисловим ідентифікатором після нього (ідентифікатор повинен бути більше нуля), або службове слово name з текстовим ідентифікатором, або обидва разом - як в даному випадку . Зовнішній модуль може звертатися до конкретного методу як за індексом, так і по імені.

Статичне  і динамічне завантаження DLL

Модуль може викликати методи іншого модуля, а той, у свою чергу, - наступного і т.д. Наприклад, додаток викликає DLL, а ця DLL викликає методи інший DLL: так можна формувати довгі ланцюжки викликів. Для виклику методу з іншого модуля необхідно спочатку завантажити його в пам'ять, а потім визначити адресу методу. Існує два способи завантаження і визначення адреси методу - статичний і динамічний.

Function Add1(K:integer):integer; stdcall; external 'Project1.DLL' name 'CalculateSum';




 При статичному  завантаженні для виклику іншого модуля слід в якійсь із секцій описати метод з DLL наступним чином:

або

function Add1(K:integer):integer; stdcall; external 'Project1.DLL' index 1; 




Для тестування необхідно  описати в додатку зовнішній  метод одним з вищезазначених способів і зробити, наприклад, обробник події OnClick кнопки, поставленої на форму разом з компонентом TEdit:

procedure TForm1.Button1Click(Sender: TObject);

var 

  N:integer; 

begin 

  N:=StrToInt(Edit1.Text); 

  N:=Add1(N); 

  Edit1.Text:=IntToStr(N); 

end; 


При натисканні кнопки буде викликатися метод з DLL. Зверніть увагу на зміну імен методу: з  обробника події OnClick викликається метод з ім'ям Add1. Цей метод  експонується в DLL під ім'ям CalculateSum. У реалізації DLL він має назву AddOne.

При такому визначенні методу DLL буде завантажена негайно після старту програми та вивантажено разом з його завершенням. У наведеному вище прикладі слід звернути увагу на те, що після імені динамічної бібліотеки зазначено її розширення (Project1.dll). Така конструкція необхідна для завантаження бібліотеки в Windows NT, оскільки без розширення *. Dll файл не буде знайдено.

При пошуку DLL для завантаження спочатку визначається, чи була дана DLL вже завантажена в пам'ять іншим модулем. Якщо була - то витягується адреса методу і передається з додатком. Якщо ж ні - то операційна система починає її пошук на диску. При цьому, якщо шлях при імені DLL не вказаний в явному вигляді, система шукає бібліотеку в каталозі модуля, який намагається завантажити DLL. Якщо не знаходить, то продовжує пошуки в директоріях WINDOWS і WINDOWS \ SYSTEM (або WINNT, WINNT \ SYSTEM, WINNT \ SYSTEM32). Після цього відбувається пошук в каталогах, визначених у змінній середовища Path. Якщо бібліотека з заданим ім'ям буде знайдена, то вона завантажиться і додаток стартує. Якщо ж ні - відбувається виключення і додаток припинить свою роботу. Додаток припиняє роботу також і в тому випадку, якщо не буде знайдений метод з даними ім'ям (або індексом, якщо він імпортується за індексом).

Динамічне завантаження DLL дозволяє завантажувати бібліотеку тільки в той момент, коли вона потрібна. Крім того, якщо не буде знайдена бібліотека або метод, то це можна проаналізувати і запустити додаток і в цьому випадку. Звичайно, в такій ситуації слід інформувати користувача про неможливість викликати метод з DLL - наприклад, зробивши невидимим пункту меню, який звертається до даного методу. Приклад динамічного завантаження DLL виглядає наступним чином:

type

  TAddFunction=function(K:integer):integer; stdcall; 

  

procedure TForm1.Button2Click(Sender: TObject); 

var 

  Add1:TAddFunction; 

  HLib:THandle; 

  N:integer; 

begin 

  HLib:=0; 

  try 

    HLib:=LoadLibrary('Project1.dll'); 

    if HLib>HINSTANCE_ERROR then begin 

      Add1:=GetProcAddress(HLib,'CalculateSum'); 

      if Assigned(Add1) then begin 

        N:=StrToInt(Edit1.Text); 

        N:=Add1(N); 

        Edit1.Text:=IntToStr(N); 

      end else ShowMessage('Метод з ім’ям CalculateSum не знайдений'); 

    end else ShowMessage('Не знайдена бібліотека Project1.dll'); 

  finally 

    if HLib>HINSTANCE_ERROR then FreeLibrary(HLib); 

  end; 

end; 


Спочатку визначається новий процедурний тип, наприклад TAddFunction, який має такий же список параметрів і такі ж домовленості виклику, що й метод в DLL. Delphi в процесі компіляції програми ніяк не може перевірити відповідність процедурного типу методу, що викликається з DLL. Перевірка може бути здійснена тільки під час виконання, а при невідповідності формальних параметрів або невірно зазначеної домовленості виклику відбувається крах стека, що програміст виявить дуже швидко.

Далі в коді програми викликається метод LoadLibrary, який як параметр використовує ім'я бібліотеки. Після успішної відпрацювання даного методу і завантаження бібліотеки в пам'ять показник на завантажену бібліотеку поміщається в змінну HLib. Якщо бібліотеку не вдається знайти або завантажити, то в цю ж змінну поміщається код помилки. Щоб визначити, чи була завантажена бібліотека, змінну HLib слід порівняти з константою HINSTANCE_ERROR, яка визначена в модулі Windows. Якщо бібліотека була успішно завантажена, то здійснюється спроба знайти адресу методу в пам'яті комп'ютера за допомогою виклику методу GetProcAddress. Зазначений метод повертає адресу того методу, ім'я якого зазначено в другому параметрі GetProcAddress. Якщо ж метод не був знайдений, то повертається nil-адресса.

Відповідно виклик методу Add1 здійснюється тільки у випадку, якщо він був успішно знайдений. Потім, оскільки при завантаженні бібліотеки були зайняті системні ресурси, їх необхідно знову повертати операційній системі, вивантаживши бібліотеку з пам'яті. Для цього викликається метод FreeLibrary. При завантаженні DLL проводиться підрахунок посилань, а саме: при кожному успішному зверненні до методу LoadLibrary в DLL лічильник посилань збільшується на одиницю, а при кожному виклику методу FreeLibrary лічильник посилань зменшується на одиницю. Як тільки лічильник посилань стане рівним нулю, бібліотека вивантажується з пам'яті комп'ютера. Отже, кожному успішному викликом LoadLibrary має відповідати звернення до FreeLibrary - інакше DLL не вивантажити з пам'яті комп'ютера навіть після закінчення роботи програми. Тому дані методи були поміщені в захищений блок try ... finally .. end; - це гарантує виклик методу FreeLibrary, якщо відбувається виключення.

Метод GetProcAddress для завантаження DLL може також використовувати індекси. Для прикладу, представленого вище, в якому метод AddOne експонується з індексом 1, використання індексів в GetProcAddress виглядає наступним чином:

Add1:=GetProcAddress(HLib,pchar(1));


При завантаженні DLL здійснюється резервування пам'яті, необхідної для  збереження коду методів. Крім того, резервується місце для всіх глобальних змінних і виконуються секції ініціалізації в модулях DLL. Якщо інший процес також намагається завантажити DLL, то знову відбувається резервування пам'яті для зберігання глобальних змінних. Проте копіювання методів DLL не здійснюється; також не виконується і секція ініціалізації. Іншими словами, одна копія методу в ОЗУ обслуговує кілька додатків. Глобальні змінні є унікальними для кожного додатку, і якщо один додаток змінить їх значення за допомогою виклику якогось методу, то інший додаток цього не помітить. Оскільки секція ініціалізації виконується тільки при першому завантаженні DLL, її не можна використовувати для установки початкових значень глобальних змінних.

Розглянемо переваги використання DLL:

  1. Методи, описані в DLL, можуть одночасно обслуговувати кілька додатків. При цьому самі методи зберігаються у вигляді однієї копії в ОЗУ. Якщо викликається код досить великий і є кілька додатків, які викликають даний код, то внаслідок цього можна досягти суттєвої економії системних ресурсів.
  2. Можливість зберігання загальних ресурсів. Якщо кілька додатків працюють з одними і тими ж ресурсами (наприклад, великі растрові картинки - *.Bmp), то при збереженні їх у DLL можна мати ці ресурси в одному екземплярі.
  3. Підтримка нових версій додатків. Якщо програміст зробив будь-які зміни в реалізаціях методів, визначених у DLL, то кінцевому споживачеві достатньо передати нову версію DLL, і *. Exe-файл можна зберегти незмінним. Це особливо актуально зараз, коли програми можна оновлювати за допомогою Internet. У цьому випадку важливо знизити кількість інформації, що посилається по мережі. Природно, що якщо частина коду реалізована в DLL, то при завантаженні з сервера тільки цієї DLL трафік, пов'язаний з оновленням версії програми, буде зменшений.
  4. Можливо використовувати різні мови програмування для створення *.Exe і *.DLL. Наприклад, *. Exe-файл може компілюватися з коду, написаного на Delphi, а *.DLL, яка їм використовується, компілюється з коду, написаного на Microsoft Visual C + +. Якщо програма використовує кілька DLL, то вони можуть бути створені на різних мовах програмування. Це значно спрощує перенесення коду в інші додатки.
  5. DLL можна завантажувати в пам'ять тільки тоді, коли вони потрібні для виконання програм, реалізуючи тим самим динамічне завантаження. При цьому знову ж досягається економія системних ресурсів. Так, наприклад, в DLL можна реалізувати діалог, за допомогою якого змінюються які небудь параметри програми. Користувач може місяцями не звертатися до даного діалогу, і при цьому DLL, в якій він реалізований, не завантажується в пам'ять і не споживає системних ресурсів. Тільки в момент, коли користувач звертається до цього діалогу, відбувається завантаження DLL в пам'ять, але після виконання діалогу ця пам'ять звільняється. Використовуючи динамічне завантаження, можна оформити динамічний призначений для користувача інтерфейс: відповідні опції меню програми з'являються в тому випадку, якщо знайдена дана DLL, і зникають при її відсутності. Такий інтерфейс зручний при поставці додатків, в яких користувач може замовити додаткові можливості за окрему плату.[1]

 

3. Реалізація

Информация о работе DLL библиотеки