Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.08.14;
Скачать: CL | DM;

Вниз

Проблема с плагинами   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.066 c
14-1121582359
Kerk
2005-07-17 10:39
2005.08.14
С днем рожденья! 17 июля


1-1122013354
InOf
2005-07-22 10:22
2005.08.14
Получить содержимое файла как символы


3-1120548686
DDDeN
2005-07-05 11:31
2005.08.14
Начало работы с InterBase


14-1121933194
SoftX
2005-07-21 12:06
2005.08.14
Астрология как историко-культурный феномен. Диссертация.


4-1119479507
dan
2005-06-23 02:31
2005.08.14
2 секунды