Assigning class method to procedure of object via class name in delphi mode

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Assigning class method to procedure of object via class name in delphi mode

cobines
Hi,

I usually use objfpc mode, however I have a few units in delphi mode
and don't know if it is a bug or normal delphi behaviour.

In the following program I have variable of type "procedure of
object". If I assign a method of a class using object name:

  CM.Callback := CM.ContextMenuSelect;

everything is ok. But I can also assign it using class name:

  CM.Callback := TContextMenu.ContextMenuSelect;

The program obviously crashes with access violation in
ContextMenuSelect on access to FFiles.

Shouldn't this give a compilation error, or is it considered a programmer error?

_______

program class_callback;

{$mode delphi}{$H+}

uses
  Classes;

type
  TNotifyProc = procedure (Sender: TObject) of object;

  TContextMenu = class
  private
    FFiles: TStringList;
  public
    Callback: TNotifyProc;
    constructor Create;
    procedure ContextMenuSelect(Sender:TObject);
  end;

constructor TContextMenu.Create;
begin
  FFiles := TStringList.Create;
  FFiles.Add('Example string');
end;

procedure TContextMenu.ContextMenuSelect(Sender:TObject);
begin
  Writeln(FFiles[0]);
end;

var
  CM: TContextMenu;
begin
  CM := TContextMenu.Create;

  // This works fine
  CM.Callback := CM.ContextMenuSelect;
  CM.Callback(CM);

  // This causes crash
  // Should this be allowed to assign?
  CM.Callback := TContextMenu.ContextMenuSelect;
  CM.Callback(CM);

  CM.free;
end.

--
cobines
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Assigning class method to procedure of object via class name in delphi mode

Anthony Walter-3
No, the assignment shouldn't be allowed. The assignment to procedure of object should only be allowed from instances.

SizeOf(TNotifyProc) = SizeOf(Pointer) * 2

See also: the TMethod record

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Assigning class method to procedure of object via class name in delphi mode

Michalis Kamburelis-3
In reply to this post by cobines
cobines wrote:
> everything is ok. But I can also assign it using class name:
>
>   CM.Callback := TContextMenu.ContextMenuSelect;
>

This is the way it's supposed to work in delphi mode, as far as I
remember Delphi allows it (disclaimer: I don't have Delphi now to check,
but it used to be so around Delphi 7).

This has actually one useful feature: when ContextMenuSelect is a "class
procedure", this is a safe and valid operation (class procedures can be
safely called by only a class reference, that's their point after all).
In objfpc I achieve the same by the unclean trick "CM.Callback :=
TContextMenu(nil).ContextMenuSelect;"

Unfortunately, the way it's implemented in delphi, it also allows this
very unsafe assignment when ContextMenuSelect is a normal (not class)
method.

Michalis
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Assigning class method to procedure of object via class name in delphi mode

cobines
2010/1/25 Michalis Kamburelis <[hidden email]>:
> This is the way it's supposed to work in delphi mode, as far as I
> remember Delphi allows it (disclaimer: I don't have Delphi now to check,
> but it used to be so around Delphi 7).

I see. I suspected as much, but wanted to make sure it's not a bug,
since I never used Delphi.

Thanks for explanation.

--
cobines
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal