从类引用创建的表单中执行方法 (Delphi)

发布于 2024-09-04 14:24:25 字数 1072 浏览 6 评论 0原文

我有一个表单(form2),并且实现了以下 PUBLIC 方法:

function ShowInterface(i:integer):boolean;

此表单位于将动态加载的包中。现在我想实例化这个表单(form2)并执行上面的方法。

重要提示:我无法在 form1 中引用 form2 的单位。

我尝试了这段代码,但它从未找到“ShowInterface”指针(返回零)。

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;

提前致谢。

I have a form (form2) and I implemented the following PUBLIC method:

function ShowInterface(i:integer):boolean;

This form is in a package that will be DYNAMIC LOADED. Now I want to instantiate this form (form2) and execute the method above.

Important: I can't reference form2's unit in form1.

I tryed this code, but it never finds "ShowInterface" pointer (returns 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;

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

世俗缘 2024-09-11 14:24:25

MethodAddress 仅适用于已发布方法。将其移至已发布部分,它应该可以工作。

或者,如果您有 Delphi 2010,则扩展 RTTI 提供了一种按名称查找公共方法的方法。 (或者其他可见性级别,如果您将其更改为默认值。)

MethodAddress only works for published methods. Move it to the published section and it should work.

Or, if you have Delphi 2010, the extended RTTI offers a way to find public methods by name. (Or other visibility levels, if you change it from the default.)

丢了幸福的猪 2024-09-11 14:24:25

正如 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;

As Mason and TOndrej said, I have to put the method in published section. (Thank you!)

But, some fixes were needed:

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;
讽刺将军 2024-09-11 14:24:25

在 D2007 和一些早期版本中,仅适用于已发布 方法或扩展 RTTI:{$METHODINFO ON}。我还没用过D2010;似乎有一个新的 RTTI 系统,已经扩展了很多。

In D2007 and some earlier versions, that only works with published methods, or extended RTTI: {$METHODINFO ON}. I haven't used D2010 yet; it seems to have a new RTTI system which has been extended a lot.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文