views:

1960

answers:

3

I fear this is probably a bit of a dummy question, but it has me pretty stumped.

I'm looking for the simplest way possible to pass a method of an object into a procedure, so that the procedure can call the object's method (e.g. after a timeout, or maybe in a different thread). So basically I want to:

  • Capture a reference to an object's method.
  • Pass that reference to a procedure.
  • Using that reference, call the object's method from the procedure.

I figure I could achieve the same effect using interfaces, but I thought there was another way, since this "procedure of object" type declaration exists.

The following doesn't work, but might it help explain where I'm confused...?

interface 
  TCallbackMethod = procedure of object;

  TCallbackObject = class
    procedure CallbackMethodImpl;
    procedure SetupCallback;
  end;

implementation

procedure CallbackTheCallback(const callbackMethod: TCallbackMethod);
begin
  callbackMethod();
end;

procedure TCallbackObject.CallbackMethodImpl;
begin
  // Do whatever.
end;

procedure TCallbackObject.SetupCallback;
begin
  // following line doesn't compile - it fails with "E2036 Variable required"
  CallbackTheCallback(@self.CallbackMethodImpl);
end;

(Once the question is answered I'll remove the above code unless it aids the explanation somehow.)

+11  A: 

Just remove the Pointer stuff. Delphi will do it for you:

procedure TCallbackObject.SetupCallback;
begin
  CallbackTheCallback(CallbackMethodImpl);
end;
knight_killer
Impressively simple, thanks!
MB
+1  A: 

The reason you don't need the pointer syntax is that you've declared the method type as a procedure of object. The compiler will figure out from the "of object" statement how to handle passing the method off the callback proc.

Jody Dawkins
I see - thanks :)
MB
A: 

OT and follow up question: What is the difference between using a callback procedure and a regular procedure. If the main use of a callback procedure is to be able to pass a procedure in the calling routine, wouldn't it be the same if we just call a procedure from inside a procedure?

Because now you can do things like this: `MyForm.Button1.OnClick := MyDataModule.Button1Click` where `TMyDataModule` has a `procedure Button1Click(Sender: TObject)`. This does work for events, parameters, etc. It allows for decoupling, which is a great aid in making your software more maintainable.
Jeroen Pluimers