Вниз  Delphi
- 23.09.2012 / 11:40
XakepPRO
  Модератор форума

XakepPRO 
Сейчас: Offline
Создание динамических библиотек DLL

Автор: STRATEG

Понимая как начинающему непросто самому понять, как создавать динамические библиотеки (Dynamic Link Library), я решил написать эту статью, в которой постараюсь раскрыть основные принципы работы с Dll в Delphi.

Для начала нужно знать почему в некоторых случаях лучше сделать Dll, а не просто Модуль. Возможно, в нескольких ваших приложениях окажется одинаковый блок кода, не совсем малых размеров, вы можете сделать Модуль и подключить его к каждому проекту, но размер EXE файла будет больше, нежели когда вы создадите одну Dll, и будете её использовать во многих программах. Когда вы работаете с динамической библиотекой, вы значительно экономите память, так как в нее загружается всего один экземпляр Dll для всех программ.

Что же могут Динамические библиотеки:
- Хранить в них звуки, картинки, иконки, курсоры и многое другое
- Использоваться в качестве плагинов (для того чтобы не редактировать сам файл программы)
- Помещать туда диалоговые, простые окна; меню и всевозможные другие ресурсы
- Давать возможность другим программистам использовать вашу библиотеку на других языках


Перейдем от теории к практики.
Напишем Dll, которая будет содержать в себе две математические функции:
1) Вычисление Факториала числа.
2) Нахождение суммы двух чисел.

Для начала нужно создать Dll в Delphi, для этого делаем следующее: "File -> New -> Other -> Dll Wizard". Появится проект вашей новой Dll. Теперь напишем наши две функции:
  1. function Fucktorial(N: integer): integer; stdcall;
  2. var p: integer;
  3. begin
  4.   for p := 1 to N do N := N*P;
  5.   Result := N;
  6. end;
  7.  
  8. function Symma(a,b: integer): Integer; stdcall;
  9. begin
  10.   Result := a+b;
  11. end;

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

Далее мы должны сделать чтобы эти функции были доступны извне. Для этого существует ключевое слово Exports. Вот так выглядит в нашей программе экспортирование:
  1. exports Fucktorial,Symma;

Теперь когда Dll готова, сохраним её под именем Math (имя, конечно, может быть любое): "File -> Save Project As"


Неявная(статическая) загрузка
Осталось создать приложение, которое будет использовать функции нашей Dll. "File->New->Application".

Для примера я поместил на форму: два TEdit, два TButton, один TLabel

После ключегого слова implementation объявим наши функции таким образом:
  1. function Symma(a,b:integer):Integer; stdcall; external 'Math.dll';
  2. function Fucktorial(N:integer):integer; stdcall; external 'Math.dll';

Как можно заметить здесь присутствует незнакомое слово external. Так мы определяем где находится наша функция, и откуда её вызывать. В нашем проекте мы вызываем функции из только что созданной Dll.

Напишем код в наши Button:
  1. //суммирование двух чисел
  2. procedure TForm1.btn1Click (Sender: TObject);
  3. var a, b, c:integer;  //переменные для чисел
  4. begin
  5.  a:=StrToInt(edt1.text);
  6.  b:=StrToInt(edt2.text);
  7.  C:=Symma(a,b);
  8.  lblResult.Caption := 'Результат:' + IntToStr(C);
  9. end;
  10.  
  11. //расчет факториала
  12. procedure TForm1.btn2Click(Sender: TObject);
  13. var N:Integer;
  14. begin
  15.  N:=StrToInt(edt1.text);
  16.  lblResult.Caption := 'Результат:' + IntToStr(Fucktorial(N));
  17. end;

Осталось лишь скомпилировать приложение и можно проверять его работу.

Теперь нужно сказать пару слов о проблемах,которые могут возникнуть. Ваша Dll должна находиться в следующих местах: рядом с программой, System. Если библиотека не найдена программой в этих местах-то появляется неприятное сообщение об ошибке, и ваша программа сразу завершит свою работу, это недостаток неявной (статической) загрузки Dll, далее мы рассмотрим как этого избежать с помощью явной (динамической) загрузки.



Явная (Динамическая) загрузка
Сейчас мы рассмотрим Динамическую или как еще говорят Явную загрузку библиотек. Она по объему кода конечно больше чем Неявная(статическая) но зато более гибкая. Возьмем наш прошлый проект и переделаем под явную (динамическую) загрузку.
Теперь вызов выглядит вот так:
  1. //Symma теперь не на какой участок памити не указывает
  2. @Symma:=nil;                
  3. //Пытаемся загрузить Dll
  4.  dHandle:=LoadLibrary('Math.dll');          
  5. //Если загрузили то
  6.  if dHandle<>0 then                
  7.     begin
  8.     //Найдем адрес нужной функции и присвоим его переменной Symma
  9.     @Symma:=GetProcAddress(dHandle,'Symma');
  10.     //если мы нашли функции в Dll и получили её адрес то            
  11.     if @Symma<>nil then                
  12.           begin
  13.            a:=StrToInt(edt1.text);
  14.            b:=StrToInt(edt2.text);
  15.            C:=Symma(a,b);          
  16.            lblResult.Caption := 'Результат:' + IntToStr(C);
  17.            end
  18.       else              //если мы  не нашли функцию в Dll
  19.           begin
  20.            lblResult.Caption := 'Результат:Функция не найдена в Dll';                
  21.           Exit;
  22.           end;
  23.      //выгружаем Dll из памяти
  24.      FreeLibrary(dHandle);  
  25.     end
  26.     else
  27.     begin
  28.        //если Dll не может быть загружена или не найдена
  29.        lblResult.Caption := 'Результат:Библеотека не найдена';            
  30.       Exit;
  31.     end;
  32. end;

Факториал числа:
  1. procedure TForm1.btn2Click(Sender: TObject);
  2. var N:Integer;
  3. dHandle: THandle;
  4. Fucktorial: function (N:integer):integer;stdcall;
  5. begin
  6.  @Fucktorial:=nil;
  7.  dHandle:=LoadLibrary('Math.dll');  //Грузим Dll
  8.  if dHandle<>0 then    begin
  9.     @Fucktorial:=GetProcAddress(dHandle,'Fucktorial');      
  10.       if @Fucktorial<>nil then                  
  11.           begin
  12.             N:=StrToInt(edt1.text);
  13.             lblResult.Caption := 'Результат:' + IntToStr(Fucktorial(N));
  14.            end
  15.       else
  16.           begin
  17.            lblResult.Caption := 'Результат:Функция не найдена в Dll';      
  18.            Exit;
  19.           end;
  20.       FreeLibrary(dHandle);
  21.     end
  22.     else
  23.     begin
  24.       lblResult.Caption := 'Результат:Библеотека не найдена';      
  25.       Exit;
  26.     end;
  27.  
  28. end;

_____

  1. LoadLibrary (lpLibFileName: PChar): HMODULE;
Назначение:
Загружает Dll в память.
Параметры:
lpLibFileName - Путь к Dll.
Возвращаемое значение:
Ссылка на модуль библиотеки при успешной загрузке, иначе 0.

  1. GetProcAddress(hModule: HMODULE; lpProcName: LPCSTR): FARPROC;
Назначение:
Ищет в библиотеке модуль.
Параметры:
lpProcName - Имя функции
hModule - ссылка на модуль которую возвратила нам функция LoadLibrary
Возвращаемое значение:
Указатель на функцию если он найден в Dll, иначе nil.

  1. FreeLibrary (hLibModule: HMODULE): BOOL;
Назначение:
Выгружает Dll из памяти.
Параметры:
hLibModule- ссылка на модуль которую возвратила нам функция LoadLibrary
Возвращаемое значение:
True если успешно выгрузили, иначе False

Неявная(статическая) загрузка (204.46 кб.)
Явная(динамическая)_загрузка (204.7 кб.)
Книга с исходниками (1237.9 кб.)
Обмен текстом (498.73 кб.)
Обмен изображенями (599.21 кб.)
Обмен изображениями и текстом (519.75 Кб)
DLL (42.31 кб.)

Изменено aNNiMON (23.09 / 14:20) (всего 1 раз)
- 19.10.2012 / 19:25
HoldFast
  Пользователь

HoldFast 
Сейчас: Offline
Наконец допилил часы :hack:
Скрин внизу
__________________
 Да, детка, я - Король Ящериц!!!

Изменено aNNiMON (3.02 / 15:14) (всего 3 раза)


Прикрепленные файлы:
Project1.exe (531 кб.) Скачано 482 раза
- 19.10.2012 / 20:33
aNNiMON
  Супервизор

aNNiMON 
Сейчас: Offline
HoldFast, класс!!!
__________________
 let live
- 19.10.2012 / 22:38
TAPAHbl4
  Пользователь

TAPAHbl4 
Сейчас: Offline
HoldFast, супер, молодцы.
Аще могёшь :gy:
- 29.10.2012 / 21:54
Evil_Angel
  Пользователь

Evil_Angel 
Сейчас: Offline
HoldFast, cool thing! А можно SWF на мобилку? :gg:
- 30.10.2012 / 16:38
ROM
  Пользователь

ROM 
Сейчас: Offline
на делфи такое возможно написать http://dd.dynamicdiagrams.com/...1/01/orrery_2006.swf ?
- 30.10.2012 / 16:57
TAPAHbl4
  Пользователь

TAPAHbl4 
Сейчас: Offline
ROM, это вопрос или утверждение?
- 30.10.2012 / 17:02
Serg
  Пользователь

Serg 
Сейчас: Offline
TAPAHbl4, скорее это было риторическим вопросом :gy:
- 30.10.2012 / 17:31
TAPAHbl4
  Пользователь

TAPAHbl4 
Сейчас: Offline
Serg, но флэшка прикольная. НаигралсО :gg:
- 30.10.2012 / 17:33
ROM
  Пользователь

ROM 
Сейчас: Offline
вопрос... не видиш чтоли знак ?
Наверх  Всего сообщений: 276
Фильтровать сообщения
Поиск по теме
Файлы топика (3)