ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

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

     

    Інформатика, програмування

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

    Якщо ваш комп'ютер працює під управлінням операційної системи Windows, то ви не можете не знати про існування динамічних під'єднуваних бібліотек (dynamic link libraries - DLL). Достатньо поглянути на список файлів, розташованих у системному каталозі Windows. Часом кількість використовуваних операційної системою динамічних бібліотек досягає декількох сотень. Таким чином, мені здається, не варто заперечувати той факт, що DLL є невід'ємною частиною функціонування операційних систем сімейства Microsoft Windows. Однак для вас може бути неочевидна необхідність використання динамічних бібліотек при розробці додатків. У межах цієї статті ми поговоримо про принципи функціонування DLL і їх використання в процесі створення ваших власних програм.

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

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

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

    Screen.Cursors [myCursor] : = LoadCursor (HInstance, MYCURSOR');

    LoadCursor - Функція Windows API, яка викликається додатком з динамічної бібліотеки User 32.dll. До речі, прикладом збережених у динамічній бібліотеці ресурсів можуть бути такі стандартні діалоги Windows, як діалог відкриття файлу, діалог друку або настройки принтера. Ці діалоги знаходяться у файлі Comctl32.dll. Однак багато прикладні розробники використовують функції виклику форм цих діалогів, абсолютно не замислюючись, де зберігається їх опис.

    Другий тип процедур - це ті, які використовуються тільки всередині самого файлу бібліотеки.

    Аргументи на користь використання DLL

    Отже, перш ніж перейти до обговорення структури динамічних бібліотек, необхідно поговорити про ті переваги, які надає їх використання розробнику. По-перше, це повторне використання коду. Думаю, ні необхідності пояснювати зручність використання один раз розроблених процедур і функцій при створенні декількох додатків? Крім того, надалі ви зможете продати деякі зі своїх бібліотек, не розкриваючи вихідних кодів. А чому тоді це краще компонентів, запитаєте ви? А тим, що функції, що зберігаються в бібліотеці, можуть бути викликані на виконання з програм, розроблених не на Object Pascal, а, наприклад, з використанням C + + Builder, Visual Basic, Visual C + + і т.д. Такий підхід накладає деякі обмеження на принцип розробки бібліотеки, але це можливо. Звучить заманливо? Мені здається, навіть дуже. Але це ще не все.

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

    По-третє, варто поговорити ось про що. Лише кілька років тому при розробці програмного забезпечення ви могли абсолютно не хвилюватися щодо розповсюдження ваших продуктів де-небудь, крім вашої країни. Я хочу сказати, що проблема перекладу на інші мови тексту на елементи керування (пункти меню, кнопки, списки, що випадають, підказки), повідомлень про помилки і т.д. НЕ стояла так гостро, як зараз. Однак, з повсюдним впровадженням Інтернету у вас з'явилася можливість битрой передачі готових програмних продуктів практично в будь-яку точку світу. І що будуть робити з вашою програмою де-небудь у Об'єднаних Арабських Еміратах, якщо крім як по-російськи, вона з користувачем спілкуватися не вміє? Ви самі можете оцінити цей ефект, якщо хоч раз на екрані вашого комп'ютера замість з дитинства знайомого російської мови з'являється «Арабська в'язь» (наприклад, через «збій» шрифтів). Отже, вже зараз ви повинні планувати можливість розповсюдження ваших програм в інших країнах (якщо, звичайно, у вас є бажання отримати як можна більше прибутку). Відповідно, постає питання швидкого перекладу інтерфейсу вашої програми на інші мови. Одним із шляхів може бути створення ресурсів інтерфейсів усередині DLL. Наприклад, можна створити один додаток, що у залежності від версії динамічної бібліотеки буде виводити повідомлення на різних мовах.

    Природно, вище наведені лише деякі з аргументів на користь використання динамічно підключаються бібліотек при розробці додатків. Отже, сподіваюся, ви все ще зацікавлені в тому, щоб дізнатися, як власне, DLL створюються. Якщо так, то вперед.

    Основи розробки DLL

    Розробка динамічних бібліотек не є якимсь надскладний процес, доступний лише обраним. Якщо ви досить добре знайомі з розробкою додатків на Object Pascal, то вам не складе особливих зусиль навчитися працювати з механізмом DLL. Отже, розглянемо ті особливості створення DLL, які вам необхідно знати, а в завершенні статті розробимо свою власну бібліотеку.

    Як і будь-який інший модуль, модуль динамічної бібліотеки має фіксований формат. Погляньте на лістинг, представлений нижче.

    library MyFirstDLL;

    uses

    SysUtils,

    Classes,

    Forms,

    Windows;

    procedure HelloWorld (AForm: TForm);

    begin

    MessageBox (AForm.Handle, Hello world !',

    DLL Message Box ', MB_OK or MB_ICONEXCLAMATION);

    end;

    exports

    HelloWorld;

    begin

    end.

    Перше, на що слід звернути увагу, це ключове слово library, що знаходиться вгорі сторінки. Library визначає цей модуль як модуль бібліотеки DLL. Далі йде назва бібліотеки. У нашому прикладі ми маємо справу з динамічним бібліотекою, яка містить єдину процедуру: HelloWorld. Причому зверніть увагу, що дана процедура за структурою нічим не відрізняється від тих, які ви ставите в модулі своїх додатків. Ключове слово exports сигналізує компілятору про те, що перераховані нижче функції та/або процедури повинні бути доступні з викликають додатків (тобто вони ніби «експортуються» з бібліотеки). Детальніше про механізм експорту ми поговоримо трохи пізніше.

    І, нарешті, в кінці модуля можна побачити ключові слова begin і end. Всередині даного блоку ви можете помістити код, який повинен виконуватися в процесі завантаження бібліотеки. Досить часто цей блок залишається порожнім.

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

    Опис та реалізація процедур і функцій, що викликаються в межах поточної DLL, нічим не відрізняються від їх аналогів у звичайних проектах-додатках. Їх специфіка полягає лише в тому, що викликає програма не буде мати до них доступу. Вона просто не буде нічого знати про їх існування, так само, як одні класи нічого не знають про ті методи, які описані в секції private інших класів.

    В доповнення до процедур і функцій, DLL може містити глобальні дані, доступ до яких дозволений для всіх процедур і функцій в бібліотеці. Для 16-бітних програм ці дані існували в єдиному екземплярі незалежно від кількості завантажених в оперативну пам'ять програм, які використовують поточну бібліотеку. Іншими словами, якщо одна програма змінює значення глобальної змінної a на 100, то для всіх інших програм a буде значення 100. Для 32-бітових додатків це не так. Тепер для кожного програми створюється окрема копія глобальної області даних.

    Експорт функцій з DLL

    Як вже говорилося вище, для експорту процедур і функцій з DLL, необхідно використовувати ключове слово export. Ще раз зверніть увагу на представлений вище лістинг бібліотеки MiFirstDll. Оскільки процедура HelloWorld визначена як експортована, то вона може бути викликана на виконання з інших бібліотек або додатків. Існують наступні способи експорту процедур і функцій: експорт по імені і експорт за порядковим номером.

    Найбільш розповсюджений спосіб експорту - на ім'я. Погляньмо на наведений нижче текст:

    exports

    SayHello,

    DoSomething,

    DoSomethingReallyCool;

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

    Для того, щоб визначити чи виконується ваш кодек в DLL або в зухвалій додатку, можна скористатися глобальної змінної IsLibrary. Вона приймає значення Істина в тому випадку, якщо код викликається з бібліотеки і ЛОЖЬ у разі виконання процедури або функції з викликає програми.

    Крім цього, в постачання Delphi входить дуже корисна утиліта tdump, яка надає дані про те, яка інформація експортується з вказаної DLL.

    Використання DLLProc

    Вище я вже говорив про те, що код ініціалізації динамічної бібліотеки може бути поміщений в блок begin ... end. Однак крім цього найчастіше необхідно передбачити деякі дії, що виконуються в процесі вивантаження DLL з оперативної пам'яті. На відміну від інших типів модулів, модуль DLL не має ні секції initialization, ні секції finalization. Наприклад, ви можете динамічно виділити пам'ять в головному блоці, проте не зрозуміло, де ця пам'ять повинна бути звільнена. Для вирішення цієї проблеми існує DLLProc - спеціальна процедура, яка викликається в певні моменти функціонування DLL.

    Для Спершу слід сказати про саму причини існування DLLProc. Динамічна бібліотека отримує повідомлення від EN-US '> Windows в моменти свого завантаження і вивантаження з оперативної пам'яті, а також у тих випадках, коли який-небудь черговий процес, який використовує функції та/або ресурси, що зберігаються в бібліотеці, завантажується в пам'ять. Така ситуація можливо в тому випадку, коли бібліотека необхідна для функціонування декількох style = "mso-spacerun: yes "> љ додатків. А для того, щоб ви мали можливість вказувати, що саме має відбуватися в такі моменти, необхідно описати спеціальну процедуру, яка і буде відповідальна за такі дії. Наприклад, вона може виглядати наступним чином:

    procedure MyFirstDLLProc (Reason: Integer);

    begin

    if Reason = DLL_PROCESS_DETACH then

    (DLL is unloading. Cleanup code here.)

    end;

    Однак системі зовсім не очевидно, що саме процедура MyFirstDllProc відповідальна за обробку розглянутих вище ситуацій. Тому ви повинні поставити у відповідність адресу нашої процедури глобальної змінної DLLProc. Це необхідно зробити в блоці begin ... end приблизно так:

    begin

    DLLProc : = @ MyDLLProc;

    ( Що-небудь ще, що має виконуватися в

    процесі ініціалізації бібліотеки)

    end.

    Нижче представлений код, що демонструє один з можливих варіантів застосування DLLProc.

    library MyFirstDLL;

    uses

    SysUtils,

    Classes,

    Forms,

    Windows;

    var

    SomeBuffer: Pointer;

    procedure MyFirstDLLProc (Reason: Integer);

    begin

    if Reason = DLL_PROCESS_DETACH then

    (DLL is вивантажується з пам'яті.

    Звільняємо пам'ять, виділену під буфер.)

    FreeMem (SomeBuffer);

    end;

    procedure HelloWorld (AForm: TForm);

    begin

    MessageBox (AForm.Handle, Hello world !',

    DLL Message Box ', MB_OK or MB_ICONEXCLAMATION);

    end;

    (Який-небудь код, в якому використовується SomeBuffer.)

    exports

    HelloWorld;

    begin

    (Ставимо у відповідність змінної

    DLLProc адресу нашої процедури.)

    DLLProc : = @ MyFirstDLLProc;

    SomeBuffer : = AllocMem (1024);

    end.

    Як можна побачити, як ознака того чи іншого події, в результаті якої викликається процедура MyFirstDll, є значення змінної Reason. Нижче наведені можливі значення цієї змінної.

    DLL_PROCESS_DETACH - Бібліотека вивантажується з пам'яті; використовується один раз;

    DLL_THREAD_ATTACH - В оперативну пам'ять завантажується новий процес, що використовує ресурси та/або код з даної бібліотеки;

    DLL_THREAD_DETACH - Один з процесів, що використовують бібліотеку, 'вивантажується' з пам'яті.

    Завантаження DLL

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

    Статична завантаження означає, що динамічна бібліотека завантажується автоматично при запуску на виконання використовує її застосування. Для того, щоб використовувати такий спосіб завантаження, вам необхідно скористатися ключовим словом external при описі експортованої з динамічної бібліотеки функції або процедури. DLL автоматично завантажується при старті програми, і Ви зможете використовувати будь-які експортуються з неї підпрограми точно так само, як якби вони були описані всередині модулів програми. Це найбільш легкий спосіб використання коду, який міститься у DLL. Недолік методу полягає в тому, що якщо файл бібліотеки, на який є посилання в програмі, відсутній, програма відмовиться завантажуватися.

    Сенс динамічного методу полягає в тому, що ви завантажуєте бібліотеку не при старті програми, а в той момент, коли вам це дійсно необхідно. Самі поміркуйте, адже якщо функція, описана у динамічній бібліотеці, використовується тільки за 10% запусків програми, то абсолютно немає сенсу використовувати статичний метод завантаження. Вивантаження бібліотеки з пам'яті в даному випадку також здійснюється під вашим контролем. Ще одне переваги такого способу завантаження DLL - це зменшення (зі зрозумілих причин) часу старту вашого додатки. А які ж у цього способу є недоліки? Основний, як мені здається, - це те, що використання даного методу є більш важким, ніж розглянута вище статичне завантаження. Спочатку потрібно скористатися функцією Windows API LoadLibrary. Для отримання вказівника на експортованої процедури або функції повинна використовуватися функція GetProcAddress. Після завершення використання бібліотеки DLL повинна бути вивантажено із застосуванням FreeLibrary.

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

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

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

    procedure SayHello (AForm: TForm); external myfirstdll.dll ';

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

    ...

    HelloWorld (self);

    ...

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

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

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

    procedure HelloWorld (AForm: TForm);

    external myfirstdll.dll 'index 15;

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

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

    procedure CoolProcedure;

    external myfirstdll.dll 'name DoSomethingReallyCool ';

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

    type

    THelloWorld = procedure (AForm: TForm);

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

    var

    DLLInstance : THandle;

    HelloWorld: THelloWorld;

    begin

    (завантажуємо DLL)

    DLLInstance: = LoadLibrary (myfirstdll.dll');

    (отримуємо покажчик)

    @ HelloWorld: = GetProcAddress (DLLInstance, HelloWorld');

    (викликаємо процедуру на виконання)

    HelloWorld (Self);

    ( вивантажуємо DLL з оперативної пам'яті)

    FreeLibrary (DLLInstance);

    end;

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

    procedure TForm1.DynamicLoadBtnClick (Sender: TObject);

    type

    THelloWorld = procedure (AForm: TForm);

    var

    DLLInstance: THandle;

    HelloWorld: THelloWorld;

    begin

    DLLInstance: = LoadLibrary (myfirstdll.dll');

    if DLLInstance = 0 then begin

    MessageDlg (Неможливо завантажити DLL ', mtError, [mbOK], 0);

    Exit;

    end;

    @ HelloWorld: = GetProcAddress (DLLInstance, HelloWorld');

    if @ HelloWorld nil then

    HelloWorld (Self)

    else

    MessageDlg (Не знайдена шукана процедура!. ', mtError, [mbOK], 0);

    FreeLibrary (DLLInstance);

    end;

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

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

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

    library Project2;

    (тут були коментарі)

    uses

    SysUtils,

    Classes;

    ($ R *. RES)

    begin

    end.

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

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

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

    function ShowForm: Integer; stdcall;

    var

    Form: TDLLForm;

    begin

    Form: = TDLLForm.Create (Application);

    Result: = Form.ShowModal;

    Form.Free;

    end;

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

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

    exports

    ShowForm;

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

    Угода за викликом (Calling conventions) визначає, яким чином передаються аргументи при виконанні функції. Існує п'ять основних угод: stdcall, cdecl, pascal, register і safecall. Докладніше про це можна дізнатися, подивившись розділ " Calling Conventions "у файлі допомоги Delphi.

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

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

    library DllForms;

    uses

    SysUtils,

    Classes,

    Forms,

    DllFormUnit in 'DllFormUnit.pas' (DllForm);

    ($ R *. RES)

    function ShowForm: Integer; stdcall;

    var

    Form: TDLLForm;

    begin

    Form: = TDLLForm.Create (Application);

    Result: = Form.ShowModal;

    Form.Free;

    end;

    begin

    end.

    unit TestAppUnit;

    interface

    uses

    Windows, Messages, SysUtils, Classes, Graphics,

    Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class (TForm)

    Button1: TButton;

    procedure Button1Click (Sender: TObject);

    private

    (Private declarations)

    public

    (Public declarations)

    end;

    var

    Form1: TForm1;

    function ShowForm: Integer; stdcall;

    external dllforms.dll ';

    implementation

    ($ R *. DFM)

    procedure TForm1.Button1Click (Sender: TObject);

    begin

    ShowForm;

    end;

    end.

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

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

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

    Отже, повернемося трохи назад і перерахуємо кроки, необхідні нам для роботи з вміщених у DLL MDIChild-формами.

    В динамічної бібліотеці створюємо глобальну змінну типу TApplication.

    Зберігаємо покажчик на об'єкт Application DLL в глобальній змінній.

    Об'єкту Application динамічної бібліотеки ставимо у відповідність вказівник на Application викликає програми.

    Створюємо MDIChild-форму і працюємо з нею.

    Повертаємо в первісний стан значення об'єкта Application динамічної бібліотеки і вивантажуємо DLL з пам'яті.

    Перший крок простий. Просто поміщаємо наступний код у верхній частині модуля DLL:

    var

    DllApp : TApplication;

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

    procedure ShowMDIChild (MainApp: TApplication);

    var

    Child: TMDIChild;

    begin

    if not Assigned (DllApp) then begin

    DllApp: = Application;

    Application: = MainApp;

    end;

    Child: = TMDIChild.Create (Application.MainForm);

    Child.Show;

    end;

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

    procedure MyDLLProc (Reason: Integer);

    begin

    if Reason = DLL_PROCESS_DETACH then

    ( DLL is вивантажується. Відновлюємо значення покажчика Application)

    if Assigned (DllApp) then

    Application: = DllApp;

    end;

    Замість ув'язнення.

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

    Список літератури

    Для підготовки даної роботи були використані матеріали з сайту http://www.hostmake.ru/

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status