Розробка dll в borland delphi

Розробка DLL в Borland Delphi

Виклик процедур і функцій, завантажених з DLL.

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

Ключове слово external повідомляє компілятору, що дана процедура може бути знайдена в динамічній бібліотеці (в нашому випадку - myfirstdll.dll). Далі виклик цієї процедури виглядає наступним чином:

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

Імпорт з DLL може проводитися на ім'я процедури (функції), порядковому номеру або з присвоєнням іншого імені.

У першому випадку ви просто оголошуєте ім'я процедури і бібліотеку, з якої її імпортуєте (ми це розглянули трохи вище). Імпорт за порядковим номером вимагає від вас вказівку цього самого номера:

У цьому випадку ім'я, яке ви даєте процедурою при імпорті не обов'язково має збігатися з тим, яке було вказано для неї в самій DLL. Тобто наведена вище запис означає, що ви імпортуєте з динамічної бібліотеки myfirstdll.dll процедуру, яка в ній експортувалася п'ятнадцятої, і при цьому в рамках вашого застосування цієї процедури дається ім'я SayHello.

Якщо ви з якихось причин не застосовуєте описаний вище спосіб імпорту, але тим не менш хочете змінити ім'я імпортованої функції (процедури), то можна скористатися третім методом:

Тут імпортованої процедурі CoolProcedure дається ім'я DoSomethingReallyCool. Виклик процедур і функцій, що імпортуються з динамічно завантажуваних бібліотек трохи більш складний, ніж розглянутий нами вище спосіб. В даному випадку потрібно оголосити покажчик на функцію або процедуру, яку ви збираєтеся використовувати. Пам'ятайте процедуру HelloWorld? Давайте подивимося, що необхідно зробити для того, щоб викликати її на виконання в разі динамічного завантаження DLL. По-перше, вам необхідно оголосити тип, який описував би цю процедуру:

Тепер ви повинні завантажити динамічну бібліотеку, за допомогою GetProcAddress отримати покажчик на процедуру, викликати цю процедуру на виконання, і, нарешті, вивантажити DLL з пам'яті. Нижче наведено код, що демонструє, як це можна зробити:

Як вже говорилося вище, одним з недоліків статичної завантаження DLL є неможливість продовження роботи програми при відсутності однієї або декількох бібліотек. У випадку з динамічної завантаженням у вас з'являється можливість програмно обробляти такі ситуації і не допускати, щоб програма «випадали» самостійно. По поверненню функціями LoadLibrary і GetProcAddress значенням можна визначити, чи успішно пройшла завантаження бібліотеки і знайдена в ній необхідна додатком процедура. Наведений нижче код демонструє це.

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

Розробку DLL, що містить форму, я продемонструю на прикладі.

Отже, по-перше, створимо новий проект динамічної бібліотеки. Для цього виберемо пункт меню File | New, а потім двічі клацнемо на іконку DLL. Після цього ви побачите приблизно наступний код:

Збережіть отриманий проект. Назвемо його DllForms.dpr.

Тепер слід створити нову форму. Це можна зробити по-різному. Наприклад, вибравши пункт меню File | New Form. Додайте на форму якісь компоненти. Назвемо форму DllForm і збережемо вийшов модуль під ім'ям DllFormUnit.pas.

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

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

Експортуємо нашу функцію з використанням ключового слова exports:

Компілюємо проект і отримуємо файл dllforms.dll. Ці прості кроки - все, що необхідно зробити для створення динамічної бібліотеки, що містить форму. Зверніть увагу, що функція ShowForm оголошена з використанням ключового слова stdcall. Воно сигналізує компілятору використовувати при експорті функції угоду по стандартному викликом (standard call calling convention). Експорт функції таким чином створює можливість використання розробленої DLL не тільки в додатках, створених в Delphi.

Також зверніть увагу, що значення, що повертається функцією ShowForm. відповідає значенню ShowModal. Таким чином ви можете передавати деяку інформацію про стан форми викликає додатком.

Нижче представлено два лістингу, перший з яких містить повний код файлу проекту DLL (модуль з формою тут не наводиться), а другий - модуль викликає додатки, в якому використовується тільки що розроблена нами бібліотека.

Прошу зауважити, що при експорті функції також було використано ключове слово stdcall.

Слід звернути особливу увагу на роботу з дочірніми формами в DLL. Якщо, наприклад, в зухвалій додатку головна форма має значення властивості FormStyle, рівним MDIForm, то при спробі виклику з DLL MDIChild-форми, на екрані з'явиться повідомлення про помилку, в якому буде говоритися, що немає жодної активної MDI-форми.

У той момент, коли ви намагаєтеся показати ваше дочірнє вікно, VCL перевіряє коректність властивості FormStyle головної форми додатка. Однак в нашому випадку все начебто правильно. Так у чому ж справа? Проблема в тому, що при проведенні такої перевірки, розглядається об'єкт Application, що належить не викликає додатком, а власне динамічної бібліотеці. Ну, і природно, оскільки в DLL немає головної форми, перевірка видає помилку. Для того щоб уникнути такої ситуації, треба призначити об'єкту Application динамічної бібліотеки об'єкт Application викликає програми. Природно, це запрацює тільки в тому випадку, коли зухвала програма - VCL-додаток. Крім того, перед вивантаженням бібліотеки з пам'яті необхідно повернути значення об'єкта Application бібліотеки в первісний стан. Це дозволить менеджеру пам'яті очистити оперативну пам'ять, займану бібліотекою. Отже, вам потрібно зберегти покажчик на «рідній» для бібліотеки об'єкт Application в глобальній змінній, яка може бути використана при відновленні його значення.

Отже, повернемося трохи назад і перерахуємо кроки, необхідні нам для роботи з поміщеним в DLL MDIChild-формами.
  1. У динамічній бібліотеці створюємо глобальну змінну типу TApplication.
  2. Зберігаємо покажчик на об'єкт Application DLL в глобальній змінній.
  3. Об'єкту Application динамічної бібліотеки ставимо у відповідність покажчик на Application викликає програми.
  4. Створюємо MDIChild-форму і працюємо з нею.
  5. Повертаємо в первісний стан значення об'єкта Application динамічної бібліотеки і вивантажуємо DLL з пам'яті.
Перший крок простий. Просто поміщаємо наступний код у верхній частині модуля DLL:

Потім створюємо процедуру, яка буде змінювати значення об'єкта Application і створювати дочірню форму. Процедура може виглядати приблизно так:

Все, що нам тепер необхідно зробити, - це передбачити повернення значення об'єкта Application в початковий стан. Робимо це за допомогою процедури MyDllProc:

Використання динамічно на перший погляд. DLL забезпечує широкий спектр вибору для оптимізації роботи додатків, а також роботи самих програмістів. Використовуйте DLL і, можливо, ваше життя стане легше!

Додаткову інформацію Ви можете отримати в компанії Interface Ltd.