Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2016-05

Assigning Interface method to event handler

10 messages · 4 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Graeme Geldenhuys

Hi,

Can I safely assign a method from an Interface reference to an event handler. The code below works, but I'm not sure if it is safe to do so, and allowed.

==================================
  TTestApp = class(TObject)
  private
    rpt: TFPReportReport;
    FReportFilter: IFPReportFilter; // can hold any export filter
  ...
constructor TTestApp.Create;
begin
  rpt := TFPReportReport.Create(nil);
  rpt.Author := 'Graeme Geldenhuys';
  rpt.Title := 'FPReport Demo 4 - Frames and Fonts';
  FReportFilter := TFPReportExportPDF.Create;  // PDF output
  //FReportFilter := TFPReportExportAggPas.Create;  // PNG output
  rpt.OnRenderReport := @FReportFilter.RenderReport;
  ...
end;
destructor TTestApp.Destroy;
begin
  rpt.Free;
  FReportFilter := nil;
  inherited Destroy;
end;
==================================

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Michael Van Canneyt
to Graeme Geldenhuys
Graeme Geldenhuys wrote 24 lines
Hi, Can I safely assign a method from an Interface reference to an event handler. The code below works, but I'm not sure if it is safe to do so, and allowed. ================================== TTestApp = class(TObject) private rpt: TFPReportReport; FReportFilter: IFPReportFilter; // can hold any export filter ... constructor TTestApp.Create; begin rpt := TFPReportReport.Create(nil); rpt.Author := 'Graeme Geldenhuys'; rpt.Title := 'FPReport Demo 4 - Frames and Fonts'; FReportFilter := TFPReportExportPDF.Create; // PDF output //FReportFilter := TFPReportExportAggPas.Create; // PNG output rpt.OnRenderReport := @FReportFilter.RenderReport; ... end;

I am not sure this is safe to do, since an event handler exists of 2 pointers: data and method. As far as I know, an interface does not have a data pointer.

Michael.

Graeme Geldenhuys
to Michael Van Canneyt
Michael Van Canneyt wrote
I am not sure this is safe to do, since an event handler exists of 2 pointers: data and method. As far as I know, an interface does not have a data pointer.

I don't fully understand your statement about 2 pointers? An event handler is simply a procedure of a object. When an event is triggered, that simply means the procedure is called and parameters are passed to it.

So that explains why my code worked - I'm simply calling a method of that interface. This all works as long as the interface reference stays in scope of course - which it is in my case

Regards,
Graeme

fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal http://fpgui.sourceforge.net/ My public PGP key: http://tinyurl.com/graeme-pgp
Sven Barth
to Michael Van Canneyt: I am not sure this is safe to do, since an event handler exists of 2 pointers: data and…
"Michael Van Canneyt" wrote 34 lines
On Wed, 25 May 2016, Graeme Geldenhuys wrote: > Hi, > > Can I safely assign a method from an Interface reference to an event > handler. The code below works, but I'm not sure if it is safe to do so, > and allowed. > > ================================== > TTestApp = class(TObject) > private > rpt: TFPReportReport; > FReportFilter: IFPReportFilter; // can hold any export filter > ... > > constructor TTestApp.Create; > begin > rpt := TFPReportReport.Create(nil); > rpt.Author := 'Graeme Geldenhuys'; > rpt.Title := 'FPReport Demo 4 - Frames and Fonts'; > > FReportFilter := TFPReportExportPDF.Create; // PDF output > //FReportFilter := TFPReportExportAggPas.Create; // PNG output > rpt.OnRenderReport := @FReportFilter.RenderReport; > ... > end; I am not sure this is safe to do, since an event handler exists of 2 pointers: data and method. As far as I know, an interface does not have a data pointer.

An method pointer is always automatically constructed by the compiler consisting of the address of the method (here IFPReportFilter.RenderReport) and the instance that method belongs to (in this case the FReportFilter), so this will indeed work without problems.
The question however is whether it is guaranteed to keep working and isn't merely the use of an implementation detail...

Regards,
Sven

Sven Barth
to Graeme Geldenhuys: I don't fully understand your statement about 2 pointers? An event handler is simply a…

Am 25.05.2016 13:54 schrieb "Graeme Geldenhuys" <

Show quoted text 5 lines
: On 2016-05-25 12:18, Michael Van Canneyt wrote: > I am not sure this is safe to do, since an event handler exists of 2 > pointers: data and method. As far as I know, an interface does not have

a

Show quoted text 5 lines
> data pointer. I don't fully understand your statement about 2 pointers? An event handler is simply a procedure of a object. When an event is triggered, that simply means the procedure is called and parameters are passed to it.

A "procedure of object" is in fact a TMethod record (yes that type exists) that contains the pointer to the method as well as what is going to be loaded as "Self" (the data part Michael mentioned), because without that you wouldn't know which instance this method belongs to (all instances of a class share the same code after all).

Regards,
Sven

Jonas Maebe
to Sven Barth: An method pointer is always automatically constructed by the compiler consisting of the…

Sven Barth wrote on Wed, 25 May 2016:

Show quoted text 6 lines
An method pointer is always automatically constructed by the compiler consisting of the address of the method (here IFPReportFilter.RenderReport) and the instance that method belongs to (in this case the FReportFilter), so this will indeed work without problems. The question however is whether it is guaranteed to keep working and isn't merely the use of an implementation detail...

It works by design. I can't think of a reason why it would stop working.

Jonas

Michael Van Canneyt
to Jonas Maebe
Jonas Maebe wrote 11 lines
Sven Barth wrote on Wed, 25 May 2016: > An method pointer is always automatically constructed by the compiler > consisting of the address of the method (here IFPReportFilter.RenderReport) > and the instance that method belongs to (in this case the FReportFilter), > so this will indeed work without problems. > The question however is whether it is guaranteed to keep working and isn't > merely the use of an implementation detail... It works by design. I can't think of a reason why it would stop working.

What is the self in case of an interface that is not in a FPC program ?

Michael.

Jonas Maebe
to Michael Van Canneyt: What is the self in case of an interface that is not in a FPC program ? Michael.

Michael Van Canneyt wrote on Wed, 25 May 2016:

Show quoted text 14 lines
On Wed, 25 May 2016, Jonas Maebe wrote: > Sven Barth wrote on Wed, 25 May 2016: > >> An method pointer is always automatically constructed by the compiler >> consisting of the address of the method (here IFPReportFilter.RenderReport) >> and the instance that method belongs to (in this case the FReportFilter), >> so this will indeed work without problems. >> The question however is whether it is guaranteed to keep working and isn't >> merely the use of an implementation detail... > > It works by design. I can't think of a reason why it would stop working. What is the self in case of an interface that is not in a FPC program ?

In all cases we pass the unadjusted interface pointer. Such an interface pointer is always a pointer to an interface VMT pointer/address.

The interface method is required to be able to reconstitute the interface's self pointer (the start of the instance that implements this interface) from that. In both FPC and in regular COM, that generally happens by some kind of stub code that is created for every interface method implemented by a class, which subtracts the offset of the interface's VMT in that specific class' instance layout from the passed self pointere.

Jonas