Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Визуальное программирование / Визуальное_программирование_лекция_17.doc
Скачиваний:
59
Добавлен:
07.06.2015
Размер:
91.65 Кб
Скачать
  1. Статическая загрузка библиотеки

Рассмотрим пример использования созданной библиотеки в проекте.

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TForm1 = class(TForm)

X1: TEdit;

Y1: TEdit;

Z1: TEdit;

X2: TEdit;

Y2: TEdit;

Z2: TEdit;

Button1: TButton;

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

Button2: TButton;

Button3: TButton;

Button4: TButton;

Label4: TLabel;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure Button3Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

Type

TVector3=record

X,Y,Z: Real;

end;

Function SummaryV(a,b: TVector3): TVector3;

stdcall; External 'VectorDLL.dll';

Function DifferenceV(a,b: TVector3): TVector3;

stdcall; External 'VectorDLL.dll';

Function MultiplicationV(a,b: TVector3): Real;

stdcall; External 'VectorDLL.dll';

Function AbsV(a: TVector3): Real;

stdcall; External 'VectorDLL.dll';

Function CosAngleV(a,b: TVector3): Real;

stdcall; External 'VectorDLL.dll';

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

var a,b :TVector3;

begin

a.X:=StrToFloat(X1.Text);

a.Y:=StrToFloat(Y1.Text);

a.Z:=StrToFloat(Z1.Text);

b.X:=StrToFloat(X2.Text);

b.Y:=StrToFloat(Y2.Text);

b.Z:=StrToFloat(Z2.Text);

If Sender=Button1 Then

Begin

Label1.Caption:=FloatToStr(SummaryV(a,b).X);

Label2.Caption:=FloatToStr(SummaryV(a,b).Y);

Label3.Caption:=FloatToStr(SummaryV(a,b).Z);

End;

If Sender=Button2 Then

Begin

Label1.Caption:=FloatToStr(DifferenceV(a,b).X);

Label2.Caption:=FloatToStr(DifferenceV(a,b).Y);

Label3.Caption:=FloatToStr(DifferenceV(a,b).Z);

End;

If Sender=Button3 Then

Label4.Caption:=FloatToStr(MultiplicationV(a,b));

end;

end.

  1. Динамическая загрузка библиотеки

Смысл динамического метода заключается в том, что библиотека загружается не при старте приложения, а в тот момент, когда необходимо её использование. Выгрузка библиотеки из памяти в данном случае также осуществляется под контролем программиста. Еще одно преимущества такого способа загрузки DLL - это уменьшение (по понятным причинам) времени старта приложения. Основной недостаток динамической загрузки большая сложность при создании программного кода. Сначала необходимо воспользоваться функцией Windows API LoadLibrary. Для получения указателя на экспортируемые процедуры или функции должна использоваться функция GetProcAddress. После завершения использования библиотеки DLL должна быть выгружена с применением FreeLibrary.

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

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TForm1 = class(TForm)

X1: TEdit; Y1: TEdit; Z1: TEdit;

X2: TEdit; Y2: TEdit; Z2: TEdit;

Button1: TButton;

Label1: TLabel; Label2: TLabel; Label3: TLabel;

Button2: TButton; Button3: TButton; Button4: TButton;

Label4: TLabel;

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

Type

TVector3=record

X,Y,Z: Real;

end;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

var a,b :TVector3;

Handle: THandle;

SummaryV: Function (a,b: TVector3): TVector3; stdcall;

DifferenceV: Function (a,b: TVector3): TVector3; stdcall;

MultiplicationV: Function (a,b: TVector3): Real; stdcall;

AbsV: Function (a: TVector3): Real; stdcall;

CosAngleV: Function (a,b: TVector3): Real; stdcall;

begin

// Очищаем адреса

@SummaryV:= nil;

@DifferenceV:=nil;

@MultiplicationV:= nil;

@AbsV:=nil;

@CosAngleV:= nil;

Handle:=LoadLibrary('VectorDLL.dll');

If Handle<32 Then

Begin

ShowMessage('Не найдена библиотека VectorDLL.dll');

Halt

End;

//Определяем адреса функций

@SummaryV:= GetProcAddress(Handle,'SummaryV');

@DifferenceV:=GetProcAddress(Handle,'DifferenceV');

@MultiplicationV:= GetProcAddress(Handle,'MultiplicationV');

@AbsV:=GetProcAddress(Handle,'AbsV');

@CosAngleV:= GetProcAddress(Handle,'CosAngleV');

a.X:=StrToFloat(X1.Text);

a.Y:=StrToFloat(Y1.Text);

a.Z:=StrToFloat(Z1.Text);

b.X:=StrToFloat(X2.Text);

b.Y:=StrToFloat(Y2.Text);

b.Z:=StrToFloat(Z2.Text);

If Sender=Button1 Then

Begin

Label1.Caption:=FloatToStr(SummaryV(a,b).X);

Label2.Caption:=FloatToStr(SummaryV(a,b).Y);

Label3.Caption:=FloatToStr(SummaryV(a,b).Z);

End;

If Sender=Button2 Then

Begin

Label1.Caption:=FloatToStr(DifferenceV(a,b).X);

Label2.Caption:=FloatToStr(DifferenceV(a,b).Y);

Label3.Caption:=FloatToStr(DifferenceV(a,b).Z);

End;

If Sender=Button3 Then

Label4.Caption:=FloatToStr(MultiplicationV(a,b));

//Освобождаем библиотеку

FreeLibrary(Handle)

end;

end.

ПРИМЕЧАНИЕ: Следует воздерживаться от использования типа string в библиотечных функциях, т.к. при его использовании существуют проблемы с "разделением памяти", лучше используйте PChar, а затем при необходимости конвертируйте его в string функцией StrPas.

В DLL можно размещать не только функции, но и курсоры, рисунки, иконки, меню, текстовые строки. Для загрузки ресурса нужно загрузить DLL, а затем, получив ее дескриптор, - загружать сам ресурс соответствующей функцией (LoadIcon, LoadCursor, и т.д.).

В этом разделе мы лишь немного затронем размещение в библиотеках DLL окон приложения (т.е. форм в Дельфи).

Для этого нужно создать новую DLL и добавить в нее новую форму (File -> New -> DLL, а затем - File -> New Form). Далее, если форма представляет собой диалоговое окно (модальную форму (bsDialog)), то добавляем в DLL следующую функцию (допустим, форма называется Form1, а ее класс - TForm1):

Пример 4. Размещение формы в DLL

function ShowMyDialog(Msg: PChar): Boolean; stdcall; ... exports ShowMyDialog; function ShowMyDialog(Msg: PChar): Boolean; begin   {Создаем экземпляр Form1 формы TForm1}   Form1 := TForm1.Create(Application);   {В Label1 выводим Msg}   Form1.Label1.Caption := StrPas(Msg);   {Возвращаем True только если нажата OK (ModalResult = mrOk)}   Result := (Form1.ShowModal = mrOk);   {Освобождаем память}   Form1.Free; end;

Если же нужно разместить в DLL немодальную форму, то необходимо сделать две функции - открытия и закрытия формы. При этом нужно заставить DLL запомнить дескриптор этой формы.