9743

Робота з бібліотеками динамічного підключення

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

Информатика, кибернетика и программирование

Бібліотеки динамічного підключення (Dynamic Link Library - DLL), це відкомпільований набір певних функцій. Зазвичай при розробці програм ви використовуєте так звані статичні бібліотеки (модулі), які містять деякий набір процедур та функцій

Украинкский

2014-11-30

63.5 KB

1 чел.

Лабораторна робота №1

Робота з бібліотеками динамічного підключення.

Мета роботи: Вивчення роботи з бібліотеками динамічного підключення. Створення програми для роботи з даним видом бібліотек.

Теоретична частина

Бібліотеки динамічного підключення (Dynamic Link Library - DLL), це відкомпільований набір певних функцій. Зазвичай при розробці програм ви використовуєте так звані статичні бібліотеки (модулі), які містять деякий набір процедур та функцій. Але використання статичних бібліотек має свої незручності:

  •  статична бібліотека приєднується до основної програми на етапі компіляції, тобто всі функції, що описані в даному модулі будуть існувати в програмі, а отже при її запуску займати місце в оперативній пам’яті. Може статись ситуація, що при роботі додатку жодна з функцій, які є в бібліотеці, не будуть викликані – але вони все одно будуть «висіти» в ОЗУ весь час роботи програми;
  •  статичні бібліотеки є залежними від мови програмування. Модуль (Unit), який був розроблений для мови Object Pascal (Delphi) не вдасться приєднати до програми написаної на мові C++, а отже доведеться переписувати всі функції під нову мову програмування.

Всіх цих недоліків можна уникнути при використанні DLL-бібліотек. З точки зору операційної системи (ОС) динамічна бібліотека є нічим іншим, як звичайним відкомпільований EXE-файлом з однією лише різницею, що цей файл не має точки входу в програму і являє набір відкомпільований функцій. Основна програма може в будь-який момент часу, під час виконання, приєднати DLL-бібліотеку в свій адресний простір, викликати потрібну функцію, а потім вивантажити з пам’яті. Тому і даний вид бібліотек називається бібліотеками динамічного підключення, так як завантаження бібліотеки в пам’ять відбувається не на етапі компіляції, а вже в процесі виконання додатку.  Такий підхід дозволяє значно зменшити об’єми оперативної пам’яті при роботі основної програми, так як бібліотека завантажується в пам’ять лише при необхідності викликати певні функції, після чого – вивантажується.  Також бібліотеки динамічного підключення в деякій мірі вирішують проблему сумісності на рівні мов програмування – бібліотека містить вже відкомпільований текст функцій, а отже не грає ролі мова програмування основної програми. Слід звернути увагу на те, що DLL завантажується в адресний простір основної програми, а отже, якщо декілька додатків одночасно використовують одну і ту ж саму бібліотеку, то для кожного з них буде створений власний екземпляр бібліотеки і всі дані, з якими оперують функції бібліотеки, не будуть перекриватись.

Ще однією з особливостей DLL є можливість зберігати в таких бібліотеках деякі програмні ресурси (зображання, звуки, анімацію) та певні елементи графічного інтерфейсу користувача (Graphic User InterfaceGUI) – модальні та немодальні вікна, що дає можливість створення досить гнучких програмних продуктів.

Створення DLL.

 В даній роботі всі приклади будуть представлені на мові програмування Object Pascal (досить часто її називають Delphi, що в корні є невірним. Delphiце середовище розробки, тобто графічна оболонка для компілятора мови Object Pascal. Тому будьте обережні з термінологією). Але дозволяється використання інших мов програмування. Принципи розробки та назви функцій ідентичні в різних середовищах.

Спочатку потрібно створити проект для динамічної бібліотеки. Для цього потрібно зайти «File\New\Other\DLL Wizard» (за точність шляху не ручаюсь – залежить від версії).  Одразу збережіть проект в окрему папку. Середовище розробки автоматично згенерує шаблон по якому буде створюватись бібліотека. Взагалі  візьміть за звичку: окремий проект – окрема папка. І ще одне попередження: ВИКОРИСТОВУЙТЕ ЗРОЗУМІЛІ НАЗВИ ДЛЯ ЗМІННИХ ТА ОБ’ЄКТІВ!!! Ніяких Form1, Form2, Project1 і т.д.  !!! За таке відношення зніматимуться бали (майте совість – Ви ж студенти КСМ). Тому одразу проект називайте зрозуміло. Не використовуйте в назвах змінних  транслітерації з української мови (наприклад, змінній ryadok не місце у вашій програмі). Використовуйте короткі зрозумілі назви англійською мовою.

В принципі написання бібліотеки динамічного підключення нічим не відрізняється від написання простої статичної бібліотеки. Розглянемо приклад розробки функції знаходження максимуму серед двох чисел.

uses

 SysUtils,

 Classes;

{$R *.res}

function Max(a,b:integer):integer;

begin

if a>b then Max:=a else Max:=b;

end;

{Перелік функцій, які будуть імпортуватись}

exports

Max;

{Ініціалізацій на частина}

begin

end.

Як видно з прикладу, структура модуля дуже проста, тільки в розділ exports, потрібно помістити назви функцій, які можуть імпортуватись зовнішніми додатками. Відкомпілювати бібліотеку можна також звичайним чином. Звісно ніяка програма при цьому не запускається. Якщо все нормально у папці з вашим проектом буде  створений файл з розширенням *.DLL (DLL- Dynamic Link Library), що і буде вашою бібліотекою.

Нажаль бібліотеки динамічного підключення можуть приймати із зовнішніх додатків тільки стандартні типи даних (всередині можуть використовуватись довільні типи користувача), а саме – integer, char, double, вказівники. Як тип string, потрібно використовувати вказівник на тип char, і до закінчення рядка нуль-символом (представлення строкових змінних в мові С++). В мові Delphi присутній тип PChar, що призначений для роботи з таким типом даних. Тобто, якщо ваша функція в динамічній бібліотеці приймає або повертає строкові змінні то краще використовувати тип PChar. (Точніше кажучи самим оптимальним методом є приведення типу String до типу PChar. Якщо у вас є змінна s:string, то її можна привести так PChar(s)).

Приєднання бібліотеки.

 Для приєднання DLL до основного додатку використовується функція LoadLibrary(‘Назва_бібліотеки’). Для фанатів С++ - дана функція є функцією з набору АРІ (інтерфейс програміста) – набору функцій для роботи з ОС. Іншими словами, така ж сама функція існує для всіх мов програмування, що призначені для розробки програм під ОС Windows.

 Дана функція повертає хендл (Handle) на новостворену бібліотеку. Хендл – це 4-байтне число, що призначене для ідентифікації об’єктів ОС. Кожен об’єкт системи, чи то вікно користувача, чи то певний елемент керування мають свій 4-байтний хендл для ідентифікації в системі. В Object Pascal є спеціальний тип – THandle. Тобто в розділі var оголосіть певну змінну цього типу, а далі просто викличте функцію в потрібному місці.

Var

LibHandle:THandle;

 .

. 

.

LibHandle:=LoadLIbrary(‘Name_Lib’);

 Зрозуміло, що вказана бібліотека повинна існувати в тій папці звідки було запущено програму.

В разі неуспішного завантаження, функція повертає нульове значення.

Для тих же фанатів С++ - тип THandleце просте 4-байтне число. Можете спокійно використовувати тип int.

Наступна дія – це завантаження потрібної функції з бібліотеки. Для цього потрібно спочатку створити певний процедурний тип, який би відповідав типу функції, що буде викликана з бібліотеки. Для цього в розділі type потрібно оголосити новий процедурний тип.

Type

TDynamicFunc=function(a,b:integer):integer;

 Що таке процедурний тип – читайте в конспектах з програмування за 1-ий курс. Одне що скажу – перелік формальний змінних та типу, що повертає функція повинні бути ідентичні тим, які є в бібліотеці. Фанати С++ використовують шаблони функцій. І ще одне… Ті ж самі фанати можуть запитати: «А як це може бути так… В Дельфі ми пишемо integerАле в С++ немає такого типу. Що робити ???» Відповідаю – назва типу ролі не грає, грає розмірність типу. В Object Pascal integer – це 4-байтний тип, а отже можете сміливо використовувати тип int, який також є 4-байтним.  Назва формальних змінних також ролі не грає… Повторюю – лише розмірність вхідних та вихідних параметрів.

Потім в розділі var потрібно оголосити змінну даного процедурного типу.

Var

 DynamicFunc:TDnamicFunc;

А потім в тексті програми просто з’єднуємо нашу змінну процедурного типу з функцією із динамічної бібліотеки.

 

@DynamicFunc:=GetProcAddress(LibHandle,'Max' );

 Тут LibHandleхендл на бібліотеку. Другий параметр функції  GetProcAddress – це назва функції в бібліотеці. Зверніть увагу – обов’язкове використання знаку @ перед змінною процедурного типу. Його призначення – сумісність вказівників.  

Якщо виникла помилка  - то  @DynamicFunc буде рівне значенню nil. А далі можна  використовувати змінну DynamicFunc, як звичайну функцію (без знаку @). Наприклад,

Var

C:integer;

.

.

.

C:=DynamicFunc(10,45);

 Для вивантаження бібліотеки з пам’яті потрібно викликати функцію:

FreeLibrary(LibHandle);

 Бібліотека вивантажується з пам’яті. Зрозуміло, що після цього не можна викликати функції, які були завантажені з даної бібліотеки.

Попередження. Всі функції для роботи з бібліотеками динамічного підключення бажано використовувати у блоках try..except, або  try..finally. Погодьтесь – значно приємніше, якщо в разі помилки при виконанні програми  з’являється повідомлення про помилку, яке є зрозумілим користувачу, а не якесь системне повідомлення ОС.

Збереження форми у бібліотеці динамічного підключення.

Як вже вище згадувалось -  в бібліотеках динамічного підключення існує можливість зберігати форми користувача. Єдина відмінність – основний додаток може взаємодіяти з даними формами лише через функції, які описані в даній бібліотеці. (Можна звичайно і звертатись напряму до методів форми, просто передавши в основну програму вказівник на новостворене вікно. Але тоді втратиться сумісність з іншими мовами програмування, так як інші мови не коректно розпізнають даний вказівник).

Для того щоб додати форму до DLL, відкрийте проект для DLL-бібліотеки. Додайте до цього проекту нову форму таким самим методом як і у звичайних додатках. До вашого проекту буде додано ще один модуль з класом вікна. Збережіть його, не забуваючи про розумні назви. Пропишіть цей модуль в розділі uses основного тексту вашої DLL-бібліотеки (там де оголошуються функції). На відміну від звичайних програм, середовище не генерує автоматичне створення форм, тому відповідний код потрібно прописати вручну. Кожній формі відповідає конкретний клас, який описаний в модулі форми. Ваша задача – це створити об’єкт цього класу. Наприклад, якщо назва форми DynamicForm, то зазвичай для класу цієї форми генерується аналогічна назва, але з літерою Т перед назвою, тобто ТDynamicForm.

Отже тепер у функції, яка буде імпортуватись просто прописуємо строчку створення об’єкту класу форми.

  DynamicForm:= ТDynamicForm.Create(nil);

 Тут Createце конструктор, який викликається від класу. Йому передається один параметр – вказівник на батьківський елемент управління, з яким новостворена форма буде зв’язана. Але в нашому випадку ми передаємо пусте значення, так як в динамічній бібліотеці невідомо, до якого елементу управління потрібно прив’язуватись.

Після створення вікна, потрібно лише його вивести на екран за допомогою методу ShowModal():

 DynamicForm.ShowModal();

 

 Даний метод зображує форму на екрані у модальному режимі. Модальний режим – це режим в якому форма відображається на екран і закриває доступ до решти вікон, програми, яка її викликала, до тих пір поки цю форму не закриє користувач. Також потік, з якого викликалась дана форма припиняє своє виконання до тих пір поки не закриється форма. Тобто команди, які йдуть після DynamicForm.ShowModal(); не будуть виконуватись до тих пір, поки користувач не закриє форму.

Закриття форми не означає її знищення з пам’яті. Після вибору всіх даних з форми її потрібно знищити. Це робиться наступними командами:

 DynamicForm.Free;

DynamicForm:=nil;

 Думаю вам зрозуміло: перший рядок-це виклик деструктора, а другий рядок – це просто знищення вказівника. Ці дві команди повинні бути тільки в такому порядку і не інакше.

ЗАУВАЖЕННЯ !!! В даному випадку обов’язково форму потрібно знищити. В звичайних додатках знищенням займався, так званий, «сміттєвик», але у випадку з динамічними бібліотеками він може не коректно спрацювати, а це може призвести до засмічення пам’яті.

Для фанатиків С++ дії є аналогічними. Потрібно створити форму і у експортній функції її виводити на екран. Тобто дії аналогічні, але використовується синтаксис С++.

Завдання

Завдання на 3 бали: Створити бібліотеку динамічного підключення, в якій реалізовуються функції знаходження максимуму та мінімуму двох чисел. Приєднати цю бібліотеку до основної програми та продемонструвати її роботу.

Завдання на 4 бали: Створити бібліотеку динамічного підключення в якій би реалізовувалась функція представлення чисел у римській системі запису. Вхідний параметр – цілочисельне значення, вихідний – рядок з римським записом.

Завдання на 5 балів: Створити бібліотеку динамічного підключення, в якій би зберігалась форма, що реалізує простий калькулятор. Після закриття калькулятора в основну програму повертається останній отриманий результат, що розраховувався на калькуляторі.

Завдання на 6 балів: Бібліотеки динамічного підключення досить непогано підходять для реалізації розширення системи без перекомпіляції, тобто створення так званих модулів розширення (plug-in). Приклади: розширення функціональності Adobe Photoshop(всі фільтри в даній програмі – це plug-in’и, що приєднуються до основної програми під час виконання). Перевага такого розширення – покращення функціональності без перекомпіляції всього додатку.

Plug-in’ом може бути будь-яка бібліотека динамічного підключення, яка має одну, або декілька експортних функцій, назва та синтаксис яких відома основній програмі. При запуску основного додатку скануються всі динамічні бібліотеки на наявність даних функцій. Якщо така бібліотека знайдена, то відбувається з нею обмін по наперед визначеному алгоритму та наперед визначеними структурами даних.

Отож завдання. Реалізувати основну програму та plug-in’и до неї. Модулі розширення повинні реалізувати запуск системного калькулятора, блокнота та форми з написом «Привіт світ!!!». Кожен модуль – це окрема бібліотека.  Кожному plug-in’у повинен відповідати певний пункт в головному меню. Всі модулі розширення знаходяться в директорії звідкіля запускалась основна програма. Головне меню формується по наявності модулів розширення і при виборі конкретного пункту меню повинен запуститись конкретний plug-in. Назва модуля зберігається в самому модулі.

 


 

А также другие работы, которые могут Вас заинтересовать

58374. Урок-проект «Die Stadt» 50.5 KB
  Und jetzt wiederholen wir, was wir schon wissen. Schlagt eure Hefte auf. Schreibt das Datum eure Hefte. Heute ist der .... Januar. Ljuda und Artjom kommt an die Tafel! Ljuda nimm die Kreide und schreibe die Übungen an die Tafel.
58376. Простые вещества-металлы 43.25 MB
  Цели урока: повторить особенности строения атомов металлов и металлическую связь. Познакомить с общими физическими свойствами металлов. Оборудование: образцы металловN l Mg Zn рры соляной кислоты и медного купороса ложки серебряная стальная алюминиевая горячая вода золотое кольцо...
58378. Путешествие на космическом корабле «Планета Земля» 112 KB
  Приемы деятельности учителя: Привлечение учащихся к обсуждению проблем, организация обмена мнениями. Основная работа по созданию сценария ложится на плечи наиболее активных, творчески мыслящих, талантливых учеников во главе с учителями.
58381. Вежливое общение 84.5 KB
  Задачи: открывать значение слова вежливость; подвести к мысли о том что учиться вежливой речи значит учиться уважительному доброму отношению друг к другу.
58382. Синтаксический разбор сложного предложения 45 KB
  Познакомить с порядком синтаксического разбора сложного предложения. Лучшие предложения записываются на доске Наступила зима. основу предложения.