我有一个表单(form2),我实现了以下PUBLIC方法:
function ShowInterface(i:integer):boolean;
此表单位于动态加载的包中。现在我想实例化这个表单(form2)并执行上面的方法。
重要提示:我无法在form1中引用form2的单元。
我尝试了这段代码,但它从未找到“ShowInterface”指针(返回nil)。
procedure TfrmForm1.Button1Click(Sender: TObject);
var
PackageModule: HModule;
AClass: TPersistentClass;
ShowInterface: function (i:integer):boolean;
frm: TCustomForm;
begin
PackageModule := LoadPackage('form2.bpl');
if PackageModule <> 0 then
begin
AClass := GetClass('TfrmForm2');
if AClass <> nil then // <<-- FINE!! IT FINDS OUT 'TfrmForm2' in 'form2.bpl')
begin
frm := TComponentClass(AClass).Create(Self) as TCustomForm;
ShowInterface := frm.MethodAddress('ShowInterface'); // <<-- HERE!! ALLWAYS RETURNS "NIL"
if @ShowInterface <> nil then
ShowInterface(1);
// but if I call frm.Show, it works fine. frm is "loaded"!!!
frm.Free;
end;
DoUnloadPackage(PackageModule);
end;
end;
提前致谢。
答案 0 :(得分:5)
MethodAddress仅适用于已发布的方法。将其移至已发布的部分,它应该有效。
或者,如果你有Delphi 2010,扩展的RTTI提供了一种按名称查找公共方法的方法。 (或其他可见性级别,如果您从默认值更改它。)
答案 1 :(得分:2)
正如Mason和TOndrej所说,我必须把这个方法放在已发表的部分中。 (谢谢!)
但是,需要一些修复:
procedure TfrmForm1.Button1Click(Sender: TObject);
type
TShowInterface = function(i:integer):boolean of object;
var
PackageModule: HModule;
AClass: TPersistentClass;
Routine: TMethod;
ShowInterface : TShowInterface;
frm: TCustomForm;
begin
PackageModule := LoadPackage('form2.bpl');
if PackageModule <> 0 then
begin
AClass := GetClass('TfrmForm2');
if AClass <> nil then
begin
frm := TComponentClass(AClass).Create(Self) as TCustomForm;
Routine.Data := Pointer(frm);
Routine.Code := frm.MethodAddress('ShowInterface');
if Assigned(Routine.Code) then
begin
ShowInterface := TShowInterface(Routine);
ShowInterface(1); // showinterface executes a "ShowModal", so we can "free" form after this.
end;
frm.Free;
end;
DoUnloadPackage(PackageModule);
end;
end;
答案 2 :(得分:1)
在D2007和某些早期版本中,仅适用于published
方法或扩展RTTI:{$METHODINFO ON}
。我还没有用过D2010;它似乎有一个新的RTTI系统,已经扩展了很多。