Веб программирование

Delphi и *.Dll

 
 

Здравствуйте. В данной статье речь пойдёт о создании и использовании динамических библиотек на Delphi. Для чего вообще нужны динамические библиотеки? Библиотека - это исполняемый файл, содержащий какой-либо вспомогательный код. Основное приложение может подгружать библиотеки в момент запуска (статическая загрузка) и в любой момент во время выполнения (динамическая загрузка), а также в любое время выгружать их (если это не системные библиотеки, которые необходимы приложению на всё время пока оно исполняется). Загружаютсябиблиотеки с помощью API LoadLibrary. Эта функция принимает в качестве входного параметра указатель на строку с нулевым символом, содержащую имя модуля, возвращает манипулятор библиотеки, имеющий тип Cardinal. Если Вы хотите теснее поработать с динамическими библиотеками, обязательно найдите и скачайте программу - Dependency Walker. Данная утилита позволяет просматривать имена экспортируемых и импортируемых функций.

Пример 1. Загружаем библиотеку и вызываем в ней процедуру:

unit Unit1;

interface

uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;

      type
        TProc=procedure; // Прототип процедуры или функции. Может быть и с параметрами, с вовращаемым значением.

type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;

var
      Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
      hlib:thandle;
      proc:tproc;
begin
      hlib:=loadlibrary('НазваниеБиблиотеки.dll');   // получаем манипулятор библиотеки(загружаем ее)
      if hlib=0 then                        // если не удалось загрузить - возбуждаем исключение...
      raise exception.Create('Не удалось загрузить библиотеку');
      try
       @proc:=getprocaddress(hlib,pchar('ИмяПроцедуры');   // получаем указатель на процедуру...
       if proc <> nil then            // проверяем указатель...
       {Вызываем процедуру ИмяПроцедуры}
      finally
        freelibrary(hlib);         // закрываем хендл и выгружаем библиотеку.
      end;
end;

end.

Данный пример демонстрирует динамическую загрузку. Статическая же будет выглядеть так:

unit Unit1;

interface

uses
      Windows, Messages, SysUtils, Variants, 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;

Procedure ИмяПроцедуры(параметры, если есть); external имябиблиотеки;stdcall;     
Function ИмяФункции(параметры, если есть):тип возвращаемого значения;external имябиблиотеки;stdcall;

//stdcall - это соглашение о типе передачи аргументов. Используется чаше всего.

implementation

Имена процедур и функций, импортируемых/экспортируемых из библиотек, чувствительны к регистру: ProcName и procname - это не одно и то же.

Пример 2. Создание динамической библиотеки в среде Delphi. Откройте среду разработки, и в меню File выберите: New->Other->Dll Wizard Откроется юнит. Удалите всё, что там написано и введите этот код:

library MyLib;

uses windows;

function MyProc(var param1,param2:integer):integer; stdcall;
begin
    result:=param1+param2;
end;

   exports MyProc;

begin

end.

Наша первая библиотека будет содержать простенькую функцию, принимающую два числовых параметра и возвращающая их сумму. Сохраните файл в какую-либо папку, предварительно запомнив ее расположение. Скомпилируйте код, и переименуйте полученный файл в mylib.dll. Затем создайте новое приложение и напишите следующий код перед словом Implementation: Function MyFunc(parameter1,parameter2:integer):integer; stdcall; external 'mylib.dll'; Вызвать эту функцию можно в любой момент, например, по нажатию кнопки:

Procedure TForm1.Button1Click(Sender:tobject);
begin 
     ShowMessage(inttostr(MyProc(2,2))); // вычисление будет выполнено в библиотеке.
end;

В Dll нельзя располагать основной функционал программы. Чаще в виде Dll бывают выполнены различные плагины, кроме того, в них хранят ресурсы. Использование библиотек избавляет программистов от утомительной и ненужной работы по переписыванию кода: реализовал один раз в dll - и далее используй в любой программе, где это необходимо. Например, операционная система Windows (и не только) почти целиком состоит из библиотек, а программирование сводится к вызову функций и процедур, содержащихся в них. Обидно бывает видеть, как некоторые программисты-новички зачастую пытаются "изобрести велосипед", ломая голову над решением какой-либо задачи - даже не подозревая, что операционная система содержит уже готовое решение в виде какой-либо API -функции, которую просто нужно правильно вызвать. Раз уж мы отклонились от темы, пожалуй, дам очень, очень важный совет: обязательно изучите API функции операционки, под которую Вы программируете. Это сбережёт Вам массу времени и нервов. Подводные камни: * Остерегайтесь передавать в/из библиотек[и] в аргументах что-либо кроме Pchar или Integer: это может повлечь большие проблемы. Чтобы избежать проблем, Borland рекомендует использовать менеджер памяти - Borlndmm.dll - почитайте о нем в справке. * То, что библиотека освобождена, ещё вовсе не означает, что она выгружена. * Windows ведёт подсчет загрузок и выгрузок всех библиотек. Если Вы собьете баланс счетчика (неправильно подгружая/выгружая библиотеку) могут появиться глюки. Остерегайтесь этого. Если позволяет задача, подгрузите библиотеку в самом старте программы, а освобождайте в самом конце, при выходе.


Есть вопросы? Спроси на нашем форуме!!
Нет комментариев

Оставлять комментарии можно только зарегистрированным




Предупреждение: Вся информация представлена исключительно в образовательных целях.
Ни авторы, ни администрация не несут ответственности в случае ее использования в противозаконных целях.