Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
3-1120744873
fens
2005-07-07 18:01
2005.08.14
скроллинг текста


3-1120648252
Apachi
2005-07-06 15:10
2005.08.14
Как в селекте можно возращать порядковый номер записи????


3-1120723703
cvg
2005-07-07 12:08
2005.08.14
Подскажите новичку -- связь Delphi и MySQL


1-1122238282
Galiaf
2005-07-25 00:51
2005.08.14
Проблемы с новыми компонентами.


4-1117514872
Logo
2005-05-31 08:47
2005.08.14
WriteConsoleInput





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский