Выполнить метод из формы, созданной ссылкой на класс (Delphi) - PullRequest
2 голосов
/ 07 июня 2010

У меня есть форма (form2), и я реализовал следующий метод PUBLIC:

function ShowInterface(i:integer):boolean;

Эта форма находится в пакете, который будет ДИНАМИЧНО загружен. Теперь я хочу создать экземпляр этой формы (form2) и выполнить описанный выше метод.

Важное замечание: Я не могу ссылаться на юнит формы 2 в форме 1.

Я попробовал этот код, но он никогда не находит указатель «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;

Заранее спасибо.

Ответы [ 3 ]

5 голосов
/ 07 июня 2010

MethodAddress работает только для опубликованных методов. Переместите его в опубликованный раздел, и он должен работать.

Или, если у вас Delphi 2010, расширенный RTTI предлагает способ поиска открытых методов по имени. (Или другие уровни видимости, если вы измените его со значения по умолчанию.)

2 голосов
/ 07 июня 2010

Как сказали Мейсон и 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;
1 голос
/ 07 июня 2010

В D2007 и некоторых более ранних версиях это работает только с published методами или расширенным RTTI: {$METHODINFO ON}. Я еще не использовал D2010; похоже, что у него новая система RTTI, которая была значительно расширена.

...