请教一个Runtime package的问题(200分)

  • 主题发起人 主题发起人 vine
  • 开始时间 开始时间
V

vine

Unregistered / Unconfirmed
GUEST, unregistred user!
请教一个Runtime package的问题

情况如下:
Main.dpr
包含文件uMain.pas, uMain.dfm
编译为Runtime package

demo.dpk
包含文件upkForm.pas,upkForm.dfm,upkFormIntf.pas


demo.dpk包代码
//-----------------------------------------------
unit upkFormIntf;

interface

type
IpkForm=Interface
['{171C7F88-DE69-421B-A863-D28B598C50B6}']
procedure ShowPKForm;
end;

implementation

end.
//-----------------------------------------------
unit upkForm;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, upkFormIntf;

type
TpkfrmTest = class(TForm, IpkForm)
Button1: TButton;
private
public
procedure ShowPKForm;
end;

implementation

{$R *.dfm}

procedure TpkfrmTest.ShowPKForm;
begin
ShowModal;
end;

initialization
RegisterClass(TpkfrmTest);
finalization
UnRegisterClass(TpkfrmTest);

end.

//-----------------------------------------------

uMain.pas调用代码:
uses
upkFormIntf;

var
FHandle :THandle;
FForm : IpkForm;
AClass: TComponentClass;
begin
FHandle := LoadPackage('demo.bpl');
try
if @FHandle<>nil then
begin
AClass := TComponentClass(GetClass('TpkfrmTest'));
if AClass <> nil then
begin
//------ (A) ------
FForm := AClass.Create(nil) as IpkForm

FForm.ShowPKForm

FForm := nil;
//------ ------------
end

end;
finally
UnloadPackage(FHandle);
end;
end;

//-----------------------------------------------

问题出现在调用完的时候。TpkfrmTest是可以正常显示出现,也能在上面进行操作。
但在关闭时,在执行完UnloadPackage(FHandle);这句,直至end后,会报Access violation错误。
经过跟踪,demo.bpl已经释放
1)如果我注释了(A)段代码则没有问题
2)如果注释UnloadPackage(FHandle);这行代码也没有报错。

请问这是什么原因引起的,怎样解决?谢谢
 
IpkForm=Interface
['{171C7F88-DE69-421B-A863-D28B598C50B6}']
有没有注册过?

然后,跟踪一下 UnloadPackage 的过程?

觉得问题出在IpkForm的注册上?
不知是不是这样子?
 
TpkfrmTest要完全释放!在onClose加入
PkFrmTest :=nil;
 
FForm没有进行释放,可以试试:
if AClass <> nil then
begin
//------ (A) ------
FForm := AClass.Create(nil) as IpkForm;
try
FForm.ShowPKForm

finally
FForm.free;
FForm := nil;
end;
//------ ------------
end;
 
请教一下vine, 我记得你曾经回答过一个问题,我在package中的一个窗体单元使用了
initialization
RegisterClass(TpkfrmTest);
finalization
UnRegisterClass(TpkfrmTest);
但是在主程序中使用findclass时确提示不能找到TpkfrmTest类,是什么原因?
我直接用的是《Delphi 5 开发人员指南》第21章的在主程序中使用附加包例子程序,对所带例子进行编译
 
谢谢

我用下面的函数去释放包就没有问题:
procedure UnLoadAddInPackage(Module: THandle);
var
i: Integer;
M: TMemoryBasicInformation;
begin
for i := Application.ComponentCount - 1 downto 0 do
begin
VirtualQuery(GetClass(Application.Components.ClassName), M, SizeOf(M));
if (Module = 0) or (HMODULE(M.AllocationBase) = Module) then
Application.Components.Free;
end;
UnRegisterModuleClasses(Module);
UnLoadPackage(Module);
end;

但我不是不理解:没有释放怎么会有这样的问题,接口不是自动生存的吗?为什么一定要我显式释放?
还有个问题:如果我在包里面不是一个TForm类型的类,而是一个从TObject继承下来的类呢?如果使用?


另外:
to yanglih :
1)你的办法是不行的,我的接口IpkForm并没有Free这个方法。
2)主程序找不到应该是你的主程序没有Build Runtime package
 
在这里修改看看:
procedure TpkfrmTest.ShowPKForm;
begin
try
ShowModal
//感觉这里很怪!哪个Form执行ShowModal
finally
free;
end;
end;
 
FForm := nil;的时候确实释放了指针,但这时候在释放指针的时候其实是调用了TpkfrmTest._Release其实就是TComponent._Release而这里的实现根本就没有释放窗体的实例.原理你可以参考TInterfacedObject的实现。
你所需要做的是模仿TInterfacedObject,
function TInterfacedObject._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if Result = 0 then
Destroy;
end;
 
对于运行期注册的类,它可以由系统负责释放,即可以不理它。
系统对它的释放好象在 OnDestroy 之前就做好了。所以当你在
决定退出系统时,可以不必去处理包的释放动作。
 
后退
顶部