Форум: "Основная";
Текущий архив: 2005.08.14;
Скачать: [xml.tar.bz2];
ВнизПроблема с плагинами Найти похожие ветки
← →
Ded Moroz © (2005-07-21 14:29) [0]Пишу прогу на основе плагинов (bpl-пакеты) и COM-интерфейсов. Главное окно - MDI, плагины - MDIChild.
Загружаю плагины при помощи LoadPackage(); - проблем нет. После этого вызываю в плагине функцию Activate в которой
динамически создается MDIChild (родителем является Application.MainForm). Мне нужно в процессе работы выгружать некоторые плагины. Пользуюсь ф-цией UnloadPackage(). Но после ее вызова при любом событии в главной форме (вызов меню, минимизация формы и т.д.) постоянно идут ошибки на пустую область памяти. Подскажите плз последовательность действий для безошибочной выгрузки плагина.
← →
Ded Moroz © (2005-07-21 18:00) [1]???
← →
Alexander Panov © (2005-07-21 19:27) [2]Есть подозрение, что ошибка в 17-й строке.
← →
Юрий Зотов © (2005-07-21 19:57) [3]Видимо, перед выгрузкой шаблона надо уничтожить все созданные им формы и другие объекты, освободить все захваченные им ресурсы и т.п.
И после выгрузки к ним уже не обращаться.
← →
Гаврила © (2005-07-21 21:29) [4]Попробую себя в телепатии:
Поскольку используется интерфейсная модель, скорее всего дело происходит так.
Где-то остался интерфейсный указатель на объект, реализованный в плагине.
Методы _AddRef и _Release вызываются автоматичемки (например при выходе за область видимости), и идет попытка вызова _Release. Указатель не нулевой, но плагин уже выгружен
← →
Ded Moroz © (2005-07-22 17:29) [5]Привожу часть исходников:
. . .
type
TPlugin = Record
PHandle: HModule;
PfrmClass: TFormClass;
PForm: TForm;
PInterface: IInitializePlugin;
PluginActive: Boolean;
PFileName: String;
PSize: String;
PPath: String;
PName: String;
PVersion: String;
PAuthor: String;
PCompany: String;
PKernelVersionRequired: String;
PluginType: String;
PDescription: String;
PReleaseDate: String;
PReleaseTime: String;
end;
. . .
var
PlugRegistry: array of TPlugin;
. . .
function TfrmMain.LoadPluginPackage(FileName: TFileName): Boolean;
var
ProbeLoad: TPlugin;
begin
ProbeLoad.PHandle:= LoadPackage(FileName);
if ProbeLoad.PHandle = 0 then
begin
RaiseLastWin32Error();
Result:= False;
end
else
begin
SetLength(PlugRegistry, Length(PlugRegistry) + 1);
PlugRegistry[High(PlugRegistry)]:= ProbeLoad;
InitPlugin;
Result:= True;
end;
end;
procedure TfrmMain.DelICPFromRegistry(Index: Integer);
var
Last: Integer;
begin
Last:= High(PlugRegistry);
if Index < Last then
Move(PlugRegistry[Index + 1],
PlugRegistry[Index], (Last - Index) * SizeOf(PlugRegistry[Index]));
SetLength(PlugRegistry, Last);
end;
function TfrmMain.UnloadPluginPackage(FileName: String): Boolean;
var
i: Integer;
FName: String;
begin
for i:= 0 to High(PlugRegistry) do
if UpperCase(PlugRegistry[i].PFileName) = UpperCase(FileName) then
begin
try
PlugRegistry[i].PInterface.DeactivatePlugin; // DeactivatePlugin - функция в интерфейсе плагина.
FreeAndNil(PlugRegistry[i].PForm);
// PlugRegistry[i].PfrmClass:= nil;
UnloadPackage(PlugRegistry[i].PHandle);
DelICPFromRegistry(i);
Result:= True;
Exit;
except
Result:= False;
end;
end;
end;
function TfrmMain.InitPlugin: Boolean;
var
Idx: Integer;
ICP: IC_Plugin;
begin
Idx:= High(PlugRegistry);
PlugRegistry[Idx].PfrmClass:= TFormClass(GetClass("TCommon"));
if not Assigned(PlugRegistry[Idx].PfrmClass) then
begin
// Place UnloadPlugin here
Result:= False;
Exit;
end;
PlugRegistry[Idx].PForm:= PlugRegistry[Idx].PfrmClass.Create(Self);
if PlugRegistry[Idx].PForm.GetInterface(IInitializePlugin, PlugRegistry[Idx].PInterface) then
begin
ICP:= PlugRegistry[Idx].PInterface.InitializePlugin;
with PlugRegistry[Idx] do
begin
PFileName:= LastICPName;
PSize:= LastICPSize;
PPath:= LastICPPath;
PluginType:= ICP.PluginType;
PName:= ICP.Name;
PAuthor:= ICP.Author;
PCompany:= ICP.Company;
PDescription:= ICP.Description;
PKernelVersionRequired:= ICP.KernelVersionRequired;
PReleaseDate:= ICP.ReleaseDate;
PReleaseTime:= ICP.ReleaseTime;
PVersion:= ICP.Version;
end;
end;
PlugRegistry[Idx].PluginActive:= PlugRegistry[Idx].PInterface.ActivatePlugin; // ActivatePlugin - функция в интерфейсе плагина.
Result:= True;
end;
Код плагина:
. . .
var
Common: TCommon;
MyForm: TForm;
Kernel: IKernelInterface;
. . .
function TCommon.InitializePlugin: IC_Plugin;
var
ICP: IC_Plugin;
begin
ICP.Author:= "Someone";
ICP.Company:= "Рога и Копыта";
ICP.Description:= "Описание плагина";
ICP.KernelVersionRequired:= "0.00";
ICP.Name:= "суперплагин";
ICP.PluginType:= "System";
ICP.Version:= "v0.00";
Result:= ICP;
end;
procedure TCommon.ShowModule_Settings(Sender: TObject);
begin
MyForm:= TpForm.Create(Application.MainForm);
MyForm.FormStyle:= fsMDIChild;
MyForm.Parent:= Application.MainForm;
MyForm.Show;
// MyForm.WindowState:= wsMaximized;
end;
function TCommon.ActivatePlugin: Boolean;
begin
if Application.MainForm.GetInterface(IKernelInterface, Kernel) then
begin
Kernel.CreateMainMenu("Tools", nil);
Kernel.CreateSubMenu("Tools", "TP", ShowModule_Settings);
end;
Result:= True;
end;
function TCommon.DeactivatePlugin: Boolean;
begin
try
if Application.MainForm.GetInterface(IKernelInterface, Kernel) then
begin
Kernel.DestroySubMenu("Tools", "TP");
Kernel.DestroyMainMenu("Tools");
if MyForm <> nil then
begin
MyForm.Parent:= Self;
FreeAndNil(MyForm);
// MyForm.Free;
end;
end;
// Kernel:= nil;
Result:= True;
except
Result:= False;
end;
end;
initialization
if not Assigned(GetClass("TCommon")) then RegisterClass(TCommon);
finalization
if Assigned(GetClass("TCommon")) then UnRegisterClass(TCommon);
end.
← →
Slym © (2005-07-23 09:42) [6]Пусть плагин запоминает созданные контролы (контролы уведомляют плагин о создании/уничтожении) во внутреннем списке и при выгрузке их уничтожает.
← →
Ded Moroz © (2005-07-23 11:36) [7][6] Он их уничтожает - DeactivatePlugin. Но проблема не решается
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.08.14;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.016 c