Execute a method from a form created by class reference (Delphi)

痞子三分冷 提交于 2019-12-21 21:35:47

问题


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.


回答1:


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.)




回答2:


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;



回答3:


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.



来源:https://stackoverflow.com/questions/2991934/execute-a-method-from-a-form-created-by-class-reference-delphi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!