13.3. ПРИМЕР
Рассмотрим пример создания DLL, в котором иллюстрируются различные приемы объявления экспортируемых подпрограмм. Для примера выбран модуль cmpix, описанный в гл. 12. В его состав входят 4 процедуры, реализующие действия с комплексными числами. Вариант соответствующей DLL показан ниже.
Для создания заготовки библиотечного модуля выберите опцию меню File | New | Unit или в окне репозитория щелкните по пиктограмме Da. В ответ Delphi откроет специальное окно проекта с длинным комментарием, в котором указывается на необходимость вставить ссылку на модуль ShareMem, если библиотека экспортирует длинные строки в параметрах обращения к подпрограммам или как результат функций. Эта ссылка должна быть первой как в предложении uses библиотеки, так и в uses файла проекта программы, которая использует эту библиотеку. Если подпрограммы библиотеки экспортируют строки ShortString или PChar, ссылаются на ShareMem не обязательно. Сразу же сохраните проект под именем Сmpix, чтобы Delphi автоматически исправила имя библиотеки в предложении Library.
Library Cmplx;
uses
SysUtils, Classes;
{$R *.RES}
type
TComplex = record Re, Im: Real;
end; function AddC(x, y: TComplex): TComplex; stdcall;
begin
Result.Im := x.Im + y.Im;
Result.Re := x.Re + y.Re end;
function SubC(x, y: TComplex): TComplex;
stdcall;
begin
Result.Im := x.Im - y.Im;
Result.Re := x.Re - y.Re
end;
function MulC(x, у: TComplex): TComplex;
stdcall;
begin
Result.Re := x.Re * y.Re + x.Im * y.Im;
Result.Im := x.Re * y.Im - x.Im * y.Re
end;
function DivC(x, y: TComplex): TComplex;
stdcall;
var
z: Real;
begin
z := sqr(y.Re) + sqr(y.Im);
try
Result.Re := (x.Re * y.Re + x.Im * y.Im)/z;
Result.Im := (x.Re * y.Im - x.Im * y.Re)/z
except
Result.Re := le+309;
Result.Im := le+309
end
end;
Exports
AddC index 1 name 'ADDC' resident,
SubC index 2,
MulC index 3,
DivC index 4;
begin
end.
Обратите внимание: все функции нашей DLL используют соглашение stdcall, которое обеспечивает совместимость новых функций с функциями API Windows 32. Мы могли бы не указывать это соглашение; в этом случае компилятор использовал бы более эффективное соглашение register, но обращение к нашей DLL из программ, написанных на других языках программирования, в общем случае стало бы невозможным.
Если вы создали DLL для "внешнего" исользования (внеDelphi), объявляйте подпрограммы с директивой stdcall или safecall!
Для использования подпрограмм из DLL необходимо описать их как внешние, добавив за словом External имя библиотеки в апострофах:
Procedure MyProc; External 'MyDLL';
Как уже говорилось, подпрограмма вызывается по имени или по индексу. В нашем примере из библиотеки MyDLL вызывается подпрограмма с внешним именем 'мургос'. Если нужно сослаться на индекс подпрограммы, за именем библиотеки указывается слово index и индекс:
Procedure MyProc; External 'MyDLL' index 2;
В этом случае имя, под которым подпрограмма будет известна программе, может не совпадать с ее внешним DLL-именем. Впрочем, программист может и явно переопределить имя подпрограммы, даже если он ссылается на ее внешнее имя:
Procedure MyProc; External 'MyDLL' Name 'ExtName';
В этом варианте предполагается, что экспортируется процедура с внешним именем ' ExtName '.
После любого из указанных выше объявлений экспортируемая подпрограмма становится доступна программе и может вызываться в ней как обычная подпрограмма Object Pascal.