ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.



 

Часть 17

Глава 15. Библиотеки динамической компоновки
Библиотеки динамической компоновки (dinamic link libraries - DLL) представляют собой исполняемые модули кода и/или данных, которые могут компоноваться с приложением во время работы. DLL позволяют разработчику приложения подготавливать и обслуживать отдел
ьные компоненты приложения. При этом можно добавлять новые компоненты к скомпилированному приложению без его модификации. DLL содержит такие готовые функциональные модули, как фильтры формата файла, которые могут быть вставлены в приложение, которое гото
во их применять. Модули DLL эффективно используют память, поскольку они могут совместно использоваться несколькими одновременно работающими приложениями.
Детальное описание структуры DLL и ее использование содержится в "Руководстве программиста", Глава 10, "Библиотеки динамической компоновки". Данная глава посвящена вопросам использования DLL в приложениях Windows.
Доступ к библиотекам DLL
DLL состоит из библиотеки функций и может быть написана на разных языках программирования независимо от того, какой язык программирования используется для доступа к DLL. Объявление функции DLL в программе на Turbo Pascal аналогично объявлению внешней про
граммы.
function MyExternalRoutine(Parameter1: Word): Word; far;
external 'MYDLL' index 12;
Приведенное выше определение функции объявляет MyExternalRoutine как функцию внешнего модуля DLL, MYDLL, со значением 12. Если указанный модуль еще не загружен до загрузки приложения, объявляющего это внешний модуль, то Windows загрузит указанные модули 
в память. Поскольку компоновка производится во время запуска, для локализации программы используется заданное значение отклонения. Большинство коммерчески распространяемых DLL предоставят вам подобные значения отклонений для своих программ.
Простой пример DLL
Приведем пример библиотеки динамической компоновки для проведения некоторых простых математических вычислений. Она состоит из трех файлов:
- MATHDLL.PAS, библиотека, определяющая программы вычислений.
- MATH.PAS, модуль, определяющий интерфейс с MathDLL.
- DLLTEST.PAS, головная программа, которая использует модуль Math.
Эти файлы содержатся на ваших дистрибутивных дискетах и могут быть загружены и проверены в IDE.
library MathDll;
uses WinTypes, WinProcs;
function Power(X, Y: Real): Real; export;
begin
 Power:=Exp(Y*ln(X));
end;
function Payments(Period, Interest, Term, Principal: Real): Real;
 export;
begin
 Payments:=(Principal*Interest/Period)/(1-Power(1+
  Interest/Period, -Term*Period));
end;
function Principals(Payment, Period, Interest, Term: Real): Real;
 export;
begin
 Principals:=Payment*((1-Power(1+Interest/Period, 
  -Term*Period))/(Interest/Period));
end;
procedure WriteError(Window: HWnd; ErrorMessage: PChar); export;
var S: String;
begin
 MessageBox(Window, ErrorMessage, 'Error'. mb_OK);
end;
exports Power       index 1;
exports Payments    index 2;
exports Principals  index 3;
exports WriteError  index 4;
begin
end.
Для использования этой библиотеки программ в программе на Turbo Pascal вам нужно создать модуль, который импортирует программы из DLL. Ниже приведен модуль, который делает доступными все четыре программы из MathDLL:
unit Math;
interface
function Power(X, Y: Real): Real;
function Payments(Period, Interest, Term, Principal: Real): Real;
function Principals(Payment, Period, Interest, Term: Real): Real;
procedure WriteError(Window: HWnd; ErrorMessage: PChar)
implementation
function Power;          external 'MathDLL' index 1;
function Payments;       external 'MathDLL' index 2;
function Principals;     external 'MathDLL' index 3;
function WriteError;     external 'MathDLL' index 4;
end.
Обратите внимание на то, что все эти программы реализованы как far, поскольку они приводятся в секторе интерфейса модуля.
Для использования функций библиотеки все что требуется от вашей программы, это включить Math в uses. Ваше приложение не должно заботиться о том, чтобы эти вызываемые программы действительно находились в библиотеке. Это проявится потом.
Например, следующая программа использует модуль Math для выполнения некоторых вычислений:
program DLLTest;
{$R MATH}
uses WinTypes. WinProcs, WObjects, Math;
type
 TMyApplication=object(TApplication)
  procedure InitMainWindow; virtual;
 end;
 TPaymentDlg=object(TDialog)
  Period, Interest, Term, Principal: Real;
  Function LoadFields: Boolean;
  procedure OK(var Msg: TMessage); virtual id_First+id_Ok;
 end;
 TPrincipalDlg=object(TDialog)
  Payment, Period, Interest, Term: Real;
  function LoadFields: Boolean;
  procedure OK(var Msg: TMessage); virtual id_First+id_Ok;
 end;
 PMyWindow=^TMyWindow;
 TMyWindow=object(TWindow)
  PaymentDlg: TPaymentDlg;
  PrincipalDlg: TPrincipalDlg;
  constructor Init(AParent: PWindowsObject; ATitle: PChar);
  procedure Payment(var Msg: TMessage); virtual cm_First+201;
  procedure Principal(var Msg: TMessage); virtual cm_First+202;
 end;
function TPaymentDlg.LoadFields: Boolean;
var
 E: Integer;
 S: String;
begin
 LoadFields:=False;
 S[0]:=Char(GetDlgItemText(HWindow, 104, @S[1], 20));
 Val(S, Interest, E);
 if E <> 0 then Exit;
 S[0]:=Char(GetDlgItemText(HWindow, 105, @S[1], 20));
 Val(S, Term, E);
 if E <> 0 then Exit;
 S[0]:=Char(GetDlgItemText(HWindow, 112, @S[1], 20));
 Val(S, Period, E);
 if E <> 0 then Exit;
 S[0]:=Char(GetDlgItemText(HWindow, 106, @S[1], 20));
 Val(S, Principal, E);
 if E <> 0 then Exit;
 LoadFields:=True;
end;
procedure TPaymentDlg.Ok(var Msg: TMessage);
var S: String;
begin
 if not LoadFields then
  WriteError(HWindow, 'All fields must have values')
 else
 begin
  Str(Payments(Period, Interest, Term, Principal):10:2, S);
  S:=S+#0;
  while S[1]=' ' do Delete(S, 1, 1);
  SetDlgItemText(HWindow, 113, @S[1]);
 end;
end;
function TPrincipalDlg.LoadFields: Boolean;
var
 E: Integer;
 S: String;
begin
 LoadFields:=False;
 S[0]:=Char(GetDlgItemText(HWindow, 104, @S[1], 20));
 Val(S, Interest, E);
 if E <> 0 then Exit;
 S[0]:=Char(GetDlgItemText(HWindow, 105, @S[1], 20));
 Val(S, Term, E);
 if E <> 0 then Exit;
 S[0]:=Char(GetDlgItemText(HWindow, 112, @S[1], 20));
 Val(S, Period, E);
 if E <> 0 then Exit;
 S[0]:=Char(GetDlgItemText(HWindow, 106, @S[1], 20));
 Val(S, Payment, E);
 if E <> 0 then Exit;
 LoadFields:=True;
end;
procedure TPrincipalDlg.Ok(var Msg: TMessage);
var S: String;
begin
 if not LoadFields then
  WriteError(HWindow, 'All fields must have values')
 else
 begin
  Str(Principals(Payment, Period, Interest, Term):10:2, S);
  S:=S+#0;
  while S[1]=' ' do Delete(S, 1, 1);
  SetDlgItemText(HWindow, 113, @S[1]);
 end;
end;
constructor TMyWindow.Init(AParent: PWindowsObject; ATitle: PChar);
begin
 TWindow.Init(AParent, ATitle);
 Attr.Menu:=LoadMenu(HInstance, 'Menu');
end;
procedure TMyWindow.Payment(var Msg: TMessage);
begin
 PaymentDlg.Init(@Self, 'PaymentDlg');
 PaymentDlg.Execute;
 PaymentDlg.Done;
end;
procedure TMyWindow.Principal(var Msg: TMessage);
begin
 PrincipalDlg.Init(@Self, 'PrincipalDlg');
 PrincipalDlg.Execute;
 PrincipalDlg.Done;
end;
procedure TMyApplication.InitMainWindow;
begin
 MainWindow:=New(PMyWindow, Init(nil, 'Title'));
end;
var MyApplication: TMyApplication;
begin
 MyApplication.Init('Hello');
 MyApplication.Run;
 MyApplication.Done;
end.



Яндекс цитирования