Recent

Author Topic: Assigning a static class methods to regular procedural variables  (Read 5905 times)

simone

  • Hero Member
  • *****
  • Posts: 573
The reference language guide states that static class methods can be assigned to regular procedural variabile.
(https://www.freepascal.org/docs-html/ref/refsu30.html)

Nevertheless the following code generate the error:

Incompatible types: got "<class method type of procedure(TObject) of object;Register>" expected "<procedure variable type of procedure(TObject) of object;Register>"

Why? Thanks in advance for explanations!

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2. {$mode objfpc}{$H+}
  3.  
  4. interface
  5.  
  6. uses
  7.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     procedure FormCreate(Sender: TObject);
  12.   end;
  13.  
  14.   Handler=class
  15.     class procedure OnClick(Sender : TObject); static;
  16.   end;
  17.  
  18. var
  19.   Form1: TForm1;
  20.   Button1 : TButton;
  21.  
  22. implementation
  23.  
  24. {$R *.lfm}
  25.  
  26. class procedure Handler.OnClick(Sender: TObject);
  27. begin
  28.   ShowMessage('Ok');
  29. end;
  30.  
  31. procedure TForm1.FormCreate(Sender: TObject);
  32. begin
  33.   Button1:=TButton.Create(Self);
  34.   Button1.Parent:=Self;
  35.   Button1.Left:=100;
  36.   Button1.Top:=100;
  37.   Button1.OnClick:=@Handler.OnClick;  //<--- ERROR
  38. end;
  39.  
  40. end.
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: Assigning a static class methods to regular procedural variables
« Reply #1 on: January 06, 2018, 12:45:07 am »
Regular procedural variable probably means this:
Code: Pascal  [Select][+][-]
  1. TRegProcVar = procedure(Sender: TObject); //of object;
i.e. not method.
But it does not work too:
Code: Pascal  [Select][+][-]
  1. var aRPV: TRegProcVar;
  2. begin
  3.   aRPV:=@Handler.OnClick;
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Assigning a static class methods to regular procedural variables
« Reply #2 on: January 06, 2018, 01:03:14 am »
Regular procedure variable is just a simple pointer.
Method variable is a record of two pointers.
Static class methods can be assigned to the first type, but you seem you want to assign them to the second type. Here is how to do it:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. var
  3.   e:TMethod;
  4. begin
  5.   Button1:=TButton.Create(Self);
  6.   Button1.Parent:=Self;
  7.   Button1.Left:=100;
  8.   Button1.Top:=100;
  9.   e.Data:=nil;
  10.   e.Code:=@Handler.OnClick;
  11.   Button1.OnClick:=TNotifyEvent(e);
  12.   //Button1.OnClick:=@Handler.OnClick;  //<--- ERROR
  13. end;

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: Assigning a static class methods to regular procedural variables
« Reply #3 on: January 06, 2018, 01:06:00 am »
Finally, this works, but requires delphi mode (and remove @):
Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$H+}
  2. ...
  3. TRegProcVar = procedure(Sender: TObject);
  4. ...
  5. var aRPV: TRegProcVar;
  6. begin
  7.   aRPV:=Handler.OnClick;
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Assigning a static class methods to regular procedural variables
« Reply #4 on: January 06, 2018, 01:10:51 am »
Finally, this works, but requires delphi mode (and remove @):
Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$H+}
  2. ...
  3. TRegProcVar = procedure(Sender: TObject);
  4. ...
  5. var aRPV: TRegProcVar;
  6. begin
  7.   aRPV:=Handler.OnClick;

or:
Code: Pascal  [Select][+][-]
  1.   aRPV: TRegProcVar;
  2. begin
  3.   aRPV:=TRegProcVar(@Handler.OnClick);
  4.   aRPV(nil);

simone

  • Hero Member
  • *****
  • Posts: 573
Re: Assigning a static class methods to regular procedural variables
« Reply #5 on: January 06, 2018, 12:03:11 pm »
It was my mistake: In the documentation I underestimated the adjective 'regular' refering to procedure.

I took into consideration class methods to logically group many event handlers of different controls created dynamically in a program with a complex GUI.

Proposed solutions are very interesting from the technical point of view, but in my context could make the code less readable. So I'm looking for others solutions. Thanks!
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 1058
Re: Assigning a static class methods to regular procedural variables
« Reply #6 on: January 06, 2018, 06:51:10 pm »
No, it was a compiler bug. It has been fixed in the current development version: https://bugs.freepascal.org/view.php?id=27414

simone

  • Hero Member
  • *****
  • Posts: 573
Re: Assigning a static class methods to regular procedural variables
« Reply #7 on: January 06, 2018, 07:51:49 pm »
Thanks Jonas. Although I'm not very familiar with Delphi, I noticed the same issue with 10.2 Starter Edition...
« Last Edit: January 07, 2018, 01:31:52 am by simone »
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

clauswk

  • Newbie
  • Posts: 1
Re: Assigning a static class methods to regular procedural variables
« Reply #8 on: March 20, 2018, 03:27:43 am »
Finally, this works, but requires delphi mode (and remove @):
Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$H+}
  2. ...
  3. TRegProcVar = procedure(Sender: TObject);
  4. ...
  5. var aRPV: TRegProcVar;
  6. begin
  7.   aRPV:=Handler.OnClick;

Thank you, Blaazen. I have been looking for a solution to a similar problem for a couple of days now, and the delphi mode did it.

Claus

simone

  • Hero Member
  • *****
  • Posts: 573
Re: Assigning a static class methods to regular procedural variables
« Reply #9 on: January 11, 2023, 04:51:59 pm »
Hi all, I revive this old thread started by me almost five years ago, as I realized that the compiler bug is still present, although at the time it was stated that the same had been fixed.

No, it was a compiler bug. It has been fixed in the current development version: https://bugs.freepascal.org/view.php?id=27414
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Assigning a static class methods to regular procedural variables
« Reply #10 on: January 11, 2023, 05:14:38 pm »
if I look at the link, Jonas meant why the code from Blaazen didn't work in non Delphi modes.

Your problem is (still) that you try to assign a one pointer type (procedure type or static class method) to a two pointer type (procedure ... OF OBJECT aka TEventNotify;)

simone

  • Hero Member
  • *****
  • Posts: 573
Re: Assigning a static class methods to regular procedural variables
« Reply #11 on: January 11, 2023, 05:52:05 pm »
Sorry, but I'm not sure I understand your comment. What do you mean by one/two pointer types? The problem I see is an incompatibility between (static) class methods and callback variables. Thanks for the further explanations.
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Assigning a static class methods to regular procedural variables
« Reply #12 on: January 11, 2023, 06:38:30 pm »
Sorry, but I'm not sure I understand your comment. What do you mean by one/two pointer types? The problem I see is an incompatibility between (static) class methods and callback variables. Thanks for the further explanations.

There are multiple callbacks types. e.g.

Code: [Select]
type
    TAProcedureCallback = procedure  (parameter:TParametertype);

and

Code: [Select]

  TAMethodCallback = procedure (parameter:TParametertype) OF OBJECT;

A VCL callback like onclick is a TAMethodCallback kind of callback and implemented internally with TWO pointers. One for the address of the code (method) to call, and one for the object reference.

While the documented static method compatibility is only with the TAProcedure kind, which is ONE pointer internally. (the address of the code (procedure or static method) to call.

In this nomenclature, a method is a procedure that is not static within an object e.g.

Type
Code: [Select]

  type TBLa = class
                        procedure thisisamethod;
              end;

simone

  • Hero Member
  • *****
  • Posts: 573
Re: Assigning a static class methods to regular procedural variables
« Reply #13 on: January 11, 2023, 06:53:27 pm »
Thank you for the explanation, very clear and accurate.  Just one last doubt: in the case of non-static class methods, shouldn't there be compatibility?
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

Thaddy

  • Hero Member
  • *****
  • Posts: 14201
  • Probably until I exterminate Putin.
Re: Assigning a static class methods to regular procedural variables
« Reply #14 on: January 11, 2023, 07:06:59 pm »
No, because normal methods have a hidden self parameter and a static methods not.
Specialize a type, not a var.

 

TinyPortal © 2005-2018