ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП |
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы. |
Часть 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. |