TURBO PASCAL |
Новости
|
9.5.2. Использование DLLДля использование подпрограмм из DLL необходимо описать их как внешние, добавив за словом External имя библиотеки в апострофах: Procedure MyProc; Far; External 'MyDLL'; Обратите внимание: перед External нало обязательно указать Far. в противном случае компилятор потребует поставить точку с запятой после слова External. Как уже говорилось, подпрограмма вызывается по имени или по индексу. В нашем примере из библиотеки MyDLL вызывается подпрограмма с внешним именем 'MYPROC'. Если нужно сослаться на индекс подпрограммы, за именем библиотеки указывается слово index и индекс: Procedure MyProc; Far; External 'MyDLL' index 2; В этом случае имя, под которым подпрограмма будет известна программе, может не совпадать с ее внешним DLL— именем. Впрочем, программист может и явно переопределить имя подпрограммы, даже если он ссылается на ее внешнее имя: Procedure MyProc; Far; External 'MyDLL' Name 'ExtName'; В это варианте предполагается, что экспортируется процедура с внешним именем ' EXTNAME'. После любого из указанных выше обяъвялений экспортируемая подпрограмма становится доступна программе и может использоваться в ней как обычная подпрограмма на Паскале независимо от того, какой язык программирования использовали ее создатели. В следующей программе используется библиотека Complex, описанная на предыдущей странице. {$N+,E+} type TComplex = record Re, Im: Single end; Procedure Add(x, y: TComplex; var z: TComplex); Far; External 'Complex' ; Procedure Sub(x, y: TComplex; var z: TComplex); Far; External 'Complex' index 3; Procedure Mul(x, y: TComplex; var z: TComplex); Fae; External 'Complex' Index 4; Procedure CDiv(x, y: TComplex; var z: TComplex); Far; External 'Complex' name 'CmplxDiv'; var a,b,c: TComplex; begin {Исходные комплексные числа: 1+li, 1+21} a. Re := 1; а. Im : = 1 ; b.Re := 1; b.Im := 2; Add(a,b,с); WriteLn('Сложение : ', с.Re:3:0, c.Im:4:0,'i'); Sub (a,b,с) ; WriteLn('Вычитание: ', c.Re:3:0, c.Im:4:0,'i'); Mul (a,b,c) ; WriteLn('Умножение: ', c.Re:3:0, c.Im:4:0,'i'); CmplxDiv(a,b,с); WriteLn('Деление : ', c.Re:3:l, c.Im:4:1,'i'); end. Описанный выше способ связывания DLL с основной программой называется статическим, т.к. он реализуется компилятором и компоновщиком. В результате Windows — заголовок программы для защищенного режима будет содержать список всех DLL и загрузчик расширителя ДОС загрузит библиотеки в память одновременно с загрузкой самой программы. Программа может загружать DLL и самостоятельно (динамически) с помощью трех функций, входящих в модуль WinAPI: LoadLibrary, CetProcAddress и FreeLibrary. Следующий пример иллюстрирует технику динамической загрузки DLL Complex: {$N+,E+} Uses WinAPI; type TComplex = record Re, Im: Single end; TComplexProc = Procedure (x, y: TComplex; var z: TComplex); var a, b, c: TComplex; Add, Sub, Mul, CDiv: TComplexProc; Handle: Word; begin {Исходные комплексные числа: 1+li, 1+2i} a. Re := 1; a. Im : = 1; b.Re := 1; b.Im := 2; {Загружаем библиотеку COMPLEX.DLL) Handle := LoadLibrary('COMPLEX.DLL'); if Handle = 0 then begin WriteLn('He найдена библиотека COMPLEX.DLL'); Halt end; {Определяем адреса процедур. Три первые вызываем по индексу, четвертую - по имени. При вызове по индексу младшее слово PChar должно содержать индекс, поэтому делаем приведение типов:} @Add := GetProcAddress(Handle,PChar(Longint(1))); @Sub := GetProcAddress(Handle,PChar(Longint(2))); @Mul := GetProcAddress(Handle,PChar(Longint(3) )); @CDiv := GetProcAddress(Handle,'CmplxDiv'); {Используем библиотеку} Add(a,b,с) ; WriteLn('Сложение : ', с.Re:3:0, с.Im:4:0,'i') ; Sub(a,b,с) ; WriteLn('Вычитание: ', c.Re:3:0, c.Im:4:0,'i'); Mul(a,b,c) ; WriteLn('Умножение: ', c.Re:3:0, c.Im:4:0,'i'); CDiv(a,b,c) ; WriteLn('Деление : ', c.Re:3:1, c.Im:4:1,'i'); {После использования удаляем библиотеку из памяти} FreeLibrary(Handle) end. При вызове DLL—подпрограмм в большинстве случаев бывает необходимо передавать структурированные параметры типа записей, как тип TComplex в предыдущем примере. Поскольку DLL не могут экспортировать типы, приходится объявлять эти типы в вызывающей программе. Если Вы часто обращаетесь в своих программах к той или иной DLL, удобно создать интерфейсный модуль, содержащий объявления как подпрограмм, так и связанных с ними типов. Например: Unit Cmplx; {$N+,E+} Interface type TComplex = record Re, Im: Single end; Procedure Add (x, y: TComplex; var z: TComplex); Procedure Sub (x, y: TComplex; var z: TComplex); Procedure Mul (x, y: TComplex; var z: TComplex); Procedure CDiv(x, y: TComplex; var z: TComplex); Implementation Procedure Add; External 'Complex' index 1; Procedure Sub; External 'Complex' index 2; Procedure Mul; External 'Complex' index 3; Procedure CDiv; External 'Complex' index 4; end. Такой интерфейсный модуль существенно упрощает разработку основной программы: {$N+,E+} Uses Cmplx; var a,b,c: TComplex; begin a. Re := 1; a. Im := 1; b.Re := 1; b.Im := 2; Add(a,b,c) ; WriteLnCСложение : ', с.Re:3:0, с.Im:4:0,'i'); Sub (a,b,c); WriteLn('Вычитание: ', с.Re:3:0, с.Im:4:0,'i') ; Mul(a,b,с); WriteLn('Умножение: ', с.Re:3:0, с.Im:4:0,'i') ; CDiv(a,b,с) ; WriteLn('Деление : ', с.Re:3:1, с.Im:4:1,'i') ; end. |
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |