[fpc-pascal]Passing Methods as Callback Procedures?

Karagiannidis Savvas karagian at it.teithe.gr
Tue Dec 17 13:23:12 CET 2002


On  Monday, December 16, 2002 10:27 PM     Jon David Sawyer  wrote :


> On Mon, 2002-12-16 at 13:57, memsom at interalpha.co.uk wrote:
> > > Ok,  I've got some code that looks like this:
> > >
> > > fCollection.ForEach(@Self.DoEach);
> > >
> > > Now when DoEach() is called its Self and the Self above
> > > are not the same...
> > >
> > > Is this supposed to happen?
> >
> > Yes. 'Self' refers to the Instance you currently reside within. So:
> >
> > procedure TMyClass.dosomething(..);
> > begin
> >   //Self is the instance of TMyClass
> > end;
> >
> > procedure TCollection.ForEach(..);
> > begin
> >   //Self is the instance of TCollection
> > end;
> >
> > Therefore, as 'Self' refers to the Instance the code belongs to, Self
will
> > differ in every unique class instance.
> >
> > What is the parameter for the 'TCollection.ForEach' method? I assume
it's a
> > typed method pointer? You should be able to just use the following:
> >
> > fCollection.ForEach(DoEach); //assign this within the class that owns
'DoEach'.
> >
> > You don't *need* to use Self, unless your class is out of scope, for
example
> > accessed within a 'with' statement and clashes with a class
method/property for
> > the with'd class.
> >
> > e.g.
> >
> >   procedure TForm1.Button1Clicked(sender: TObject);
> >   begin
> >     Caption := 'wabble'; // the form
> >
> >     with sender as TButton do begin
> >
> >       Caption := 'wibble'; //the button not the form
> >
> >       Self.Caption := 'wobble'; //the form
> >
> >     end;
> >   end;
> >
> >
> > Matt
> >
> >
> I belive you missunderstood what I was trying to do:
> I had My object which used another object.  That otehr object was
> a tCollection.  tCOllection has a method in which you can pass
> a procedure to process each individual item in the collection.
>
> I was trying to pass My object's item handler , MyObject.DoEach, as
> the callback procedure for ForEach();  ie:
> fCOllection.ForEach(@Self.DoEach);
>
> The compiler doesn't complain about this code.  However the correct
> instance of the object is not called when DoEach() is called.
>
> My problem is that prior to going into ForEach() self equals something
> diffrent than when ForEach() calls DoEach().
> >

In ForEach you must pass two parameters.
The first must be a pointer to the object whose method you want to call
   and the second must be the pointer to the object's method.


Note that fCollection must accept the second parameter as a pointer to a
procedure,
but the type of the procedure is different than the object's method. The
difference between them is that
the procedure has an extra parameter, which must be the first parameter you
pass to the procedure,
and must be the pointer that points to the object whose method you wish to
call...

for example :


TDoEachProc = procedure (objptr : pointer;  ...... (actual method
parameters)  );

fCollection = class
   procedure ForEach( callbackobj : pointer; callbackproc : TDoEachProc );
end;

procedure fCollection.ForEach ( callbackobj : pointer; callbackproc :
TDoEachProc );
begin
  callbackproc( callbackobj ,  ... parameters for the method... );
end;


Now, in the other object, you can use

procedure AnObject.DoEach(...)
begin
...
end;

procedure AnObject.SetCallBack;
var p : pointer;
begin
  ...
  p := @DoEach;
  fCollection.ForEach(Self,TDoEachProc(p));
end;

This should work for you, BUT I don't think you should do something like
that!
I'm sure that there is a better way of doing what you want...






More information about the fpc-pascal mailing list