Sign in Join

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

Mailing lists / fpc-pascal / 2010-01

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

4 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

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

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
Anthony Walter
to cobines

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

Michalis Kamburelis
to cobines: I usually use objfpc mode, however I have a few units in delphi mode and don't know if it…
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

cobines
to Michalis Kamburelis

2010/1/25 Michalis Kamburelis :

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