L
longwei
Unregistered / Unconfirmed
GUEST, unregistred user!
在主程序PMain.exe中动态调用包含窗体FBase2的Basepkg2.bpl,而TBase2继承于TBase1=TForm,TBase1被包在
Basepkg.bpl这个运行期包中,这一切都正常,问题在于当我修改TBase1,具体是增加一些全程变量,如private,
public或protected变量后并重编译Basepkg.bpl,然后主程序PMain.exe再动态调用包含窗体Base2的Basepkg2.bpl,
(Basepkg2.bpl没有重新编译),并使用新增的变量,会出现如下错误:Project PMain.exe raised exception
class EAccessViolation with message'Access violation Project PMain.exe raised exception class
EAccessViolation with message'Access violation at address ???????? in module 'rtl60.bpl, ...
或其他内存访问错误,重新编译Basepkg2.bpl就没问题。
编译PMain.exe需要Build with runtime packages (Basepkg).
我的问题是在我的一个大系统中,所有的子模块所继承的基类都包含于一个运行期包中,基类经常需要修改或升级,
但我不能因此而去重新编译众多的子模块包。子模块包动态调用。
原代码如下:
主程序:
unit CMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,db, CBase1;
type
TFbasemodClass = class of TBase1;
TMain = class(TForm)
Button4: TButton;
procedure Button4Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Main: TMain;
implementation
{$R *.dfm}
procedure TMain.Button4Click(Sender: TObject);
var
hModule: THandle;
vTBase2: TBase1;
FBasemodClass :TFbasemodClass;
begin
hModule := LoadPackage('C:/Test/Basepkg2.bpl');
try
vTBase2 := TFbasemodClass(FindClass('TBase2')).Create(self);
vTBase2.ShowModal;
finally
vTBase2.Free;
UnloadPackage(hModule);
end;
end;
end.
运行期包Basepkg.bpl
package Basepkg;
{$R *.res}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$IMPLICITBUILD OFF}
requires
rtl,
vcl,
dbrtl;
contains
CBase1 in 'CBase1.pas' {Base1};
end.
基类:TBase1
unit CBase1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,db;
type
TBase1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
protected
Property1:String;
Property2:integer; //如果新增全程变量,重编译包Basepkg.bpl,而不
//编译Basepkg2.bpl,会引起以上所描述的问题。
//而修改或新增基类方法或过程不会有问题
end;
var
Base1: TBase1;
implementation
{$R *.dfm}
procedure TBase1.Button1Click(Sender: TObject);
begin
Property1:='Property1';
Property2:=10;
ShowMessage(Property1+' '+IntToStr(Property2));
end;
end.
动态包:Basepkg2.bpl
package Basepkg2;
{$R *.res}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$IMPLICITBUILD OFF}
requires
rtl,
Basepkg; //包含基类包
contains
CBase2 in 'CBase2.pas' {Base2};
end.
继承类:TBase2
unit CBase2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, CBase1, StdCtrls;
type
TBase2 = class(TBase1)
Memo1: TMemo;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Base2: TBase2;
implementation
{$R *.dfm}
initialization
RegisterClass(TBase2);
finalization
UnRegisterClass(TBase2);
end.
Basepkg.bpl这个运行期包中,这一切都正常,问题在于当我修改TBase1,具体是增加一些全程变量,如private,
public或protected变量后并重编译Basepkg.bpl,然后主程序PMain.exe再动态调用包含窗体Base2的Basepkg2.bpl,
(Basepkg2.bpl没有重新编译),并使用新增的变量,会出现如下错误:Project PMain.exe raised exception
class EAccessViolation with message'Access violation Project PMain.exe raised exception class
EAccessViolation with message'Access violation at address ???????? in module 'rtl60.bpl, ...
或其他内存访问错误,重新编译Basepkg2.bpl就没问题。
编译PMain.exe需要Build with runtime packages (Basepkg).
我的问题是在我的一个大系统中,所有的子模块所继承的基类都包含于一个运行期包中,基类经常需要修改或升级,
但我不能因此而去重新编译众多的子模块包。子模块包动态调用。
原代码如下:
主程序:
unit CMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,db, CBase1;
type
TFbasemodClass = class of TBase1;
TMain = class(TForm)
Button4: TButton;
procedure Button4Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Main: TMain;
implementation
{$R *.dfm}
procedure TMain.Button4Click(Sender: TObject);
var
hModule: THandle;
vTBase2: TBase1;
FBasemodClass :TFbasemodClass;
begin
hModule := LoadPackage('C:/Test/Basepkg2.bpl');
try
vTBase2 := TFbasemodClass(FindClass('TBase2')).Create(self);
vTBase2.ShowModal;
finally
vTBase2.Free;
UnloadPackage(hModule);
end;
end;
end.
运行期包Basepkg.bpl
package Basepkg;
{$R *.res}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$IMPLICITBUILD OFF}
requires
rtl,
vcl,
dbrtl;
contains
CBase1 in 'CBase1.pas' {Base1};
end.
基类:TBase1
unit CBase1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,db;
type
TBase1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
protected
Property1:String;
Property2:integer; //如果新增全程变量,重编译包Basepkg.bpl,而不
//编译Basepkg2.bpl,会引起以上所描述的问题。
//而修改或新增基类方法或过程不会有问题
end;
var
Base1: TBase1;
implementation
{$R *.dfm}
procedure TBase1.Button1Click(Sender: TObject);
begin
Property1:='Property1';
Property2:=10;
ShowMessage(Property1+' '+IntToStr(Property2));
end;
end.
动态包:Basepkg2.bpl
package Basepkg2;
{$R *.res}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$IMPLICITBUILD OFF}
requires
rtl,
Basepkg; //包含基类包
contains
CBase2 in 'CBase2.pas' {Base2};
end.
继承类:TBase2
unit CBase2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, CBase1, StdCtrls;
type
TBase2 = class(TBase1)
Memo1: TMemo;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Base2: TBase2;
implementation
{$R *.dfm}
initialization
RegisterClass(TBase2);
finalization
UnRegisterClass(TBase2);
end.