Взаимодействие с DLL
С самых общих позиций можно считать, что вызывающая (Master) и вызываемая (Slave) части обладают своими интерфейсами. Экспортируемая функция конструирует Slave-интерфейс и возвращает его. Экспортируемая функция играет в этом случае роль фабрики класса. Сигнатура экспортируемой функции выглядит так:
TDllFunction = function(aInterface: Pointer): Pointer; StdCall;
После вызова этой функции Master и Slave части взаимодействуют друг с другом через свои интерфейсы. В качестве интерфейса наиболее удобно использовать чистый абстрактный класс, например:
IMaster = class public procedure Method1; virtual; abstract; ............. end;
Виртуальный абстрактный класс не содержит переменных, а все его методы - виртуальные и абстрактные. Декларация интерфейса включается в обе взаимодействующие части. Для реализации интерфейса создается класс, наследуемый от абстрактного интерфейса и переписывающий все его виртуальные методы. Интерфейсный объект Master-части конструируется и удаляется в основной программе. Интерфейсный объект Slave-части конструируется в экспортируемой функции DLL, а уничтожается в блоке finalization при выгрузке DLL или с помощью другой экспортируемой функции. Например:
uses UnitIMaster, UnitISlave; type TSlaveObject = class(ISlave) private FMain: IMain; public constructor Create(aMain: IMain); destructor Destroy; override; procedure Method1; override; ............ end; function CreateSlave(aInterface: Pointer): Pointer; stdcall; function DestroySlave(aInterface: Pointer): Pointer; stdcall; implementation var SlaveObject: TSlaveObject; // Реализация TSlaveObject ............ function CreateSlave(aInterface: Pointer): Pointer; begin SlaveObject := TSlaveObject.Create(IMaster(aInterface)); result := SlaveObject; end; function DestroySlave(aInterface: Pointer): Pointer; begin SlaveObject.Free; SlaveObject := nil; result := nil; end; initialization SlaveObject := nil; finalization SlaveObject.Free; end.