Разработка программы для автоматизации работы кардиоцентра
Курсовой проект - Компьютеры, программирование
Другие курсовые по предмету Компьютеры, программирование
?ходит обращение к диспетчеру памяти, то их деструкторы нельзя вызвать за пределами модуля. В частности, если в DLL происходит исключение, то создается объект в диспетчере памяти DLL. Если не использовать ловушки исключений, то этот объект попадает в приложение и после показа пользователю сообщения приложение попытается его разрушить. В результате вновь произойдет исключение. Поэтому все экспонируемые в DLL методы, в которых могут произойти исключения, должны иметь ловушку исключения:
Типичный обмен текстовой информацией с DLL выглядит следующим образом. Если необходимо передать какую-либо строку в метод DLL, то можно просто использовать в методе указатель на строку:
procedure SendString(P:pchar); stdcall; external FirstLib.dll name SendString;
TForm1.Button5Click(Sender: TObject); :string; :=This test string will be sended to DLL; (pchar(S)); ;
Метод SendString в DLL реализован следующим образом:
SendString(P:pchar); stdcall; export; :string; :=StrPas(P);
ShowMessage(S); ;
При запуске данного примера появится сообщение, которое показывает содержимое строки, созданной в *.exe-модуле. Для того чтобы получить текстовую информацию из DLL, в приложении обычно создается буфер, который заполняется в DLL. Естественно, размер буфера должен быть достаточным для хранения всей текстовой информации. Чтобы обезопасить буфер от переполнения, вместе с буфером в качестве параметра чаще всего посылается его размер.
Вызов методов приложения в DLL
Ранее мы рассматривали только такие варианты, когда методы DLL вызываются из приложения. Но часто требуется, чтобы DLL вызывала методы приложения, например для нотификационных сообщений.
Если необходимо вызвать из приложения метод, который при этом не является методом класса, то достаточно передать указатель на метод в DLL:
var :integer=0;
CalculateSum(ReturnCallback:pointer):integer; stdcall; FirstLib.dll name Sum;
GetNextValue:integer; stdcall; NSum<200 then begin (NSum); :=NSum; else Result:=-1; ;
TForm1.Button9Click(Sender: TObject); :=IntToStr(CalculateSum(@GetNextValue));
end;
В приложении создается метод (не метод класса!), адрес которого передается в DLL. Для того чтобы данный метод можно было вызывать из DLL, созданных на других языках программирования, желательно использовать соглашение stdcall вызова при реализации указанных методов (так называемые callback-методы). Использование вызова метода в DLL можно проиллюстрировать на таком примере:
type =function:integer; stdcall;
CalculateSum(ReturnCallback:pointer):integer; stdcall; export; :integer; :TReturnNextMethod; :=0; ReturnCallback=nil then Exit; :=0; :=TReturnNextMethod(ReturnCallback); N>=0 do begin :=ReturnNext; N>=0 then Result:=Result+N;
end; ;
При необходимости вызвать метод объекта следует учитывать, что данный метод объекта характеризуется двумя адресами - адресом метода и адресом данных. Следовательно, необходимо передавать два указателя. Но вместо передачи двух указателей можно воспользоваться структурой TMethod, определенной в модуле SysUtils.pas:
type = record , Data: Pointer;
end;
Код в приложении для приведенного выше примера выглядит так:
type =function:integer of object; stdcall;
CalculateSumObject(Method:TMethod):integer; stdcall; FirstLib.dll name SumObject;
TForm1.GetNextValueObject:integer; stdcall; NSum<10 then begin (NSum); :=NSum; else Result:=-1; ;
TForm1.Button10Click(Sender: TObject); :TGetNextValueObject; :=0; :=GetNextValueObject; :=IntToStr(CalculateSumObject(TMethod(FGetNext)));
end;
Код в DLL, осуществляющий вызов метода объекта, выглядит следующим образом:
type =function:integer of object; stdcall;
CalculateSumObject(Method:TMethod):integer; stdcall; export; :integer; :TReturnNextMethodObject; :=0; :=0; :=TReturnNextMethodObject(Method); N>=0 do begin :=ReturnNext; N>=0 then Result:=Result+N;
end; ;
Следует учитывать, что методы объекта являются зависимыми от языка, то есть в разных языках программирования генерируются различные способы передачи данных в метод объекта. Поэтому данный пример следует использовать только в случае, если и приложение, и DLL написаны на Delphi (или на одном и том же языке программирования).
И наконец, само приложение может экспонировать методы таким же способом, что и DLL. В приложении можно создать секцию exports и объявить имена (и/или индексы) методов. После этого в DLL можно воспользоваться методом GetProcAddress для получения указателя на метод и вызвать его. Для описанного выше примера код приложения будет такой:
function GetNextValueExport:integer; stdcall; export;
begin NSum<10 then begin (NSum); :=NSum; else Result:=-1; ;
CalculateSumExport(HInstance:integer; MethodName:pchar):integer; stdcall;FirstLib.dll name SumExport;
TForm1.Button11Click(Sender: TObject); :integer; :=0; :=CalculateSumExport(HInstance,GetNextValueExport); :=IntToStr(N); ;
{!! The section is announced in Application !!} index 1 name GetNextValueExport;
Теперь в приложении (в проекте, где будет генерироваться *.exe-файл[U2] [NE3] ) определена секция exports! Соответствующий код в DLL для тестирования данного метода выглядит следующим образом:
type =function:integer; stdcall;
CalculateSumExport(AppInstance:integer; MethodName:pchar):integer; stdcall; export; :TReturnNextMethodExport; :integer; :=0; :=0; :=GetProcAddress(AppInstance,MethodName); N>=0 do begin :=ReturnNextExport; N>=0 then Result:=Result+N;
end; ;
При запуске этого проекта приложение автоматически загружает DLL и находит адрес метода в DLL CalculateNextExport (который экспортируется по имени SumExport). Загруженная DLL в качестве параметров получает заголовок модуля приложения и имя метода, под которым [U4] он экспортируется в приложении. Далее DLL использует метод GetProcAddress для нахождения адреса метода, экспортируемого приложением. Для того чтобы был возвращен адрес метода, в приложении объявляется секция exports, где описано внешнее имя метода. Этот пример показывает формально одинаковые структуру и способ формирования *.exe- и *.dll-файлов.
Немодальные формы в DLL
Показ немодальных форм традиционно осуществляется со статической загрузкой DLL. Вот типичный код для показа немодальной фо