ИСПОЛЬЗОВАНИЕ
13.4.1. Статическая загрузка В следующей программе используется библиотека Сmpix, описанная на предыдущей странице. Type TComplex = record Re, Im: Real; End; function ADDC(x, y: TComplex): TComplex; stdcall; External 'Cmplx'; function SubC(x, y: TComplex): TComplex; stdcall; External 'Cmplx'; function MulC(x, y: TComplex): TComplex; stdcall; External 'Cmplx'; function DivC(x, y: TComplex): TComplex; stdcall;External 'Cmplx'; procedure TfmExample.bbRunClick(Sender: TObject); Var x,y,z: TComplex; ..... // Далее смотри текст обработчика bbRunClick в п.12.6 end; end. Обратите внимание: библиотечная функция cmpixAdd имеет внешнее имя addc. Именно так (заглавными буквами) описана эта функция в приведенном выше примере. Если бы мы использовали function AddC(x, у: TComplex): TComplex; stdcall; External 'Cmplx'; компоновщик не смог бы ее идентифицировать. 13.4.2. Динамическая загрузка Описанный выше способ определения функций и процедур DLL (с помощью директивы External) заставит компилятор поместить в заголовок программы список всех DLL, и загрузчик загрузит библиотеки в память одновременно с загрузкой самой программы. Программа может загружать DLL и без External с помощью трех Стандартных функций:LoadLibrary, GetProcAddress И FreeLibrary. Следующий пример иллюстрирует технику такой загрузки DLL Cmplx: Type TComplex = record Re, Im: Real; End; TComplexFunc = function (x, y: TComplex): TComplex; Stdcall; procedure TfmExample.bbRunClick(Sender: TObject); Var x,y,z:TComplex; AddC,SubC,MulC,DivC: TComplexFunc; Handle: LongWord; procedure Output(Operation: Char); ....//Тело процедуры Output остается без изменений end;//Output begin //bbRunClick // Загружаем библиотеку CMPLX.DLL Handle:= LoadLibrary('Cmplx.dll'); if Handle = 0 then Begin ShowMessage('He найдена библиотека CMPLX.DLL'); Halt end; {Определяем адреса функций. Три первые вызываем по индексу, четвертую - по имени. При вызове по индексу младшее слово PChar должно содержать индекс, поэтому делаем приведение типов:} @AddC:= GetProcAddress(Handle,PChar(Longint (1))); PSubC:= GetProcAddress(Handle,PChar(Longint(2))); @MulC:= GetProcAddress(Handle,PChar(Longint(3))); @DivC:= GetProcAddress(Handle,'DivC'); x.re:= Random; x.im:= Random; y.re:= Random; y.im := Random; Output('+'); Output('-'); Output ('*'); Output ('/'); mmOutput.Lines.Add(''); // Освобождаем библиотеку FreeLibrary(Handle) End; 13.4.3. Интерфейсный модуль При вызове DLL-подпрограмм в большинстве случаев бывает необходимо передавать структурированные параметры типа записей, как тип TComplex в предыдущем примере. Поскольку DLL не могут экспортировать типы, приходится объявлять эти типы в вызывающей программе. Если вы часто обращаетесь в своих программах к той или иной DLL, удобно создать интерфейсный модуль, содержащий объявления как подпрограмм, так и связанных с ними типов. Например: Unit Complx; Interface Type TComplex = record Re, Im: Real; End; function AddC(x, y: TComplex): TComplex; stdcall; External 'Cmplx' index 1; function SubC(x, y: TComplex): TComplex; stdcall; External 'Cmplx' index 2; function MulC(x, y: TComplex): TComplex; stdcall; External 'Cmplx' index 3; function DivC(x, y: TComplex): TComplex; stdcall; External 'Cmplx' index 4; Implementation end. Такой интерфейсный модуль существенно упрощает разработку основной программы: в нашем примере он обеспечивает такой же интерфейс к библиотеке cmpix, как описанный выше модуль cmpix к своим объектам. При обращении к подпрограммам DLL, написанным на других языках программирования, может оказаться, что внешнее имя подпрограммы содержит символы, которые не могут содержаться в правильном идентификаторе Delphi. Например, язык C++ разрешает использовать в идентификаторах символ “@”. В этом случае (а также если вы хотите переименовать экспортируемую из DLL подпрограмму) именуйте подпрограмму любым правильным с точки зрения Delphi идентификатором и укажите истинное имя подпрограммы после слова name. Например: function MyFunction: WordBool; stdcall; external 'MyDLL' name '_MyFunction@12'
|