Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interface method as event handler

Is it possible to use interface method as event handlers in Delphi 2007? The simple versions don't work:

type
  TMyEvent = procedure of object;

  IMyInterface = interface
    procedure Handler;
  end;

  TMyClass = class(TInterfacedObject, IMyInterface)
  public
    procedure Handler;
  end;

var
  ev: TMyEvent;
  obj: TMyClass;
  intf: IMyInterface;
begin
  obj := TMyClass.Create;
  intf := obj;
  ev := obj.Handler; // compiles
  ev := intf.Handler; // <== Error E2010 (incompatible types)
end.

Adding @ or Addr changes the error to E2036 (variable required).

Update: This

procedure IntRefToMethPtr(const IntRef; var MethPtr; MethNo: Integer);
type
  TVtable = array[0..999] of Pointer;
  PVtable = ^TVtable;
  PPVtable = ^PVtable;
begin
  //QI=0, AddRef=1, Release=2, etc
  TMethod(MethPtr).Code := PPVtable(IntRef)^^[MethNo];
  TMethod(MethPtr).Data := Pointer(IntRef);
end;

var
  ev: TMyEvent;
  intf: IMyInterface;
begin
  intf := TMyClass.Create;
  IntRefToMethPtr(intf, ev, 3);
  ev;
end.

works. However I'm not too fond of the magic 3 in there.

like image 319
Uli Gerhardt Avatar asked Nov 05 '22 10:11

Uli Gerhardt


1 Answers

A cleaner solution is to implement IInterfaceComponentReference, or something similar for your base class, and uses that to get the class ref.

The above code will not work on e.g. FPC and other compatibles. Their VMT structure is slightly different. And even on Delphi a future language extension might cause this.

A perfect solution would be to have a completely separate "interface" methodvar type for this, but I wonder if that is worth the trouble.

like image 70
Marco van de Voort Avatar answered Nov 15 '22 07:11

Marco van de Voort