[Last Call] Learn about multicloud storage options and how to improve your company's cloud strategy. Register Now

x
?
Solved

Callback functions for both object and non-object functions

Posted on 2007-04-10
8
Medium Priority
?
615 Views
Last Modified: 2011-09-20
Using Delphi I want to use callback functions as parameters of a procedure.
Let's say I write an optimization routine declared as
procedure goldensearch(f: TGoalFunction;  ax, bx, cx, tol: Real; var xmin, fmin: Real);
TGoalFunction is a callback function that I can define as
TGoalFunction = function(x: Real): Real of object;
or as
TGoalFunction = function(x: Real): Real;
In the first case the function has to be a memberfunction of a class in the second case it is is not a member function.

Now I want to use the goldensearch with both object member functions en non-object functions. How do I do that? It seems now to me that I have to program two nearly identical goldensearch procedures with the only difference the parameter with and without "of object".

Is there a way to handle both situations in one implementation?
0
Comment
Question by:IgnaceLamine
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
  • 2
8 Comments
 
LVL 21

Expert Comment

by:ziolko
ID: 18882345
very simply:

function NonObjectGoal(x: Real):Real;
begin
.
.
.
end;

TSomeObject = class()
  function ObjectGoal(x: Real):Real;
end;

function TSomeObject.ObjectGoal(x: Real):Real;
begin
  Result := NonObjectGoal(x);
end;

this way you can use it in two ways:
goldensearch(NonObjectGoal, ....)
or
goldensearch(someobject.ObjectGoal, ....)

ziolko.
0
 

Author Comment

by:IgnaceLamine
ID: 18884461
If I am correct, you are saying that I should always choose the "function of object" parameter type. If my goalfunction is part of a class, then I'm lucky and can use it straight away, if it's not part of a class I should create a dummy class for it. Looks like a hack to me, but usable. I wish there were a more elegant solution.

Any other suggestions? Solutions?
0
 
LVL 21

Accepted Solution

by:
ziolko earned 800 total points
ID: 18886155
you can of course use object method as callback in same object as goldensearch() or
creating dummy class for callback only might work but that's not "elegant" way.
so i suggest two ways:
1. use non-object callback function
2. if you want to stick to objects use event that would more "delphi like" and clear to understand for most delphi devs.

TObjectGoalEvent = function(Sender:TObject;x: Real):Real of object;

TSomeClass = class(TObject)
private
  FOnObjectGoal: TObjectGoalEvent;
public
  procedure goldensearch(f: TGoalFunction;  ax, bx, cx, tol: Real; var xmin, fmin: Real);
  property OnObjectGoal: TObjectGoalEvent read FOnObjectGoal write FOnObjectGoal;
end;
.
.
.
procedure
TSomeClass.goldensearch(f: TGoalFunction;  ax, bx, cx, tol: Real; var xmin, fmin: Real);
begin
.
.
.
  if Assigned(FOnObjectGoal) then
    FOnObjectGoal(Self, your x value here);
.
.
.
end;

TCallback = class(TObject)
  function MyOnObjectGoalEventHandler(Sender: TObject;x: Real);
end;


var someobj: TSomeClass;
      callbackobj: TCallback;

someobj.OnObjectGoal := callbackobj.MyOnObjectGoalEventHandler

ziolko.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 1

Expert Comment

by:swiatlo
ID: 18888343
Investigate TMethod type in your help file.
It has two fields. Code, Data: Pointer;
Data points to an object, Code points to execution routine - method, but I think you can put a function addres in there.

var
  sp: procedure(val:Integer) of Object;
begin
      TMethod(sp).code:=funcaddr;
      TMethod(sp).data:=obj;

     if TMethod(sp).data<>nil then
       sp(5)                               //Execute as an object method
    else
       TMethod(sp).code(5) //Execute as stand alone function



0
 
LVL 1

Assisted Solution

by:swiatlo
swiatlo earned 200 total points
ID: 18888474
Myabe this would help, but I think that ziolko's warp a funciton is a better idea


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    ObjFunc: TButton;
    Edit1: TEdit;
    StdFun: TButton;
    procedure ObjFuncClick(Sender: TObject);
    procedure StdFunClick(Sender: TObject);
  private
    { Private declarations }
    function formsinttostr(val:integer):string;
    procedure ExecuteFunction(tm:TMethod);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function TForm1.formsinttostr(val:integer):string;
begin
  result:=inttostr(val);
end;

procedure TForm1.ExecuteFunction(tm:TMethod);
var
  sp: function(val:Integer):string of Object;
  fun: function(val:Integer):string;
begin

     if tm.data<>nil then
       begin
         TMethod(sp).code:=tm.code;
         TMethod(sp).data:=tm.data;
         Edit1.Text:=sp(5);                              //Execute as an object method
       end
     else
       begin
         fun:=tm.Code;
         Edit1.Text:=fun(7);            //Execute as stand alone function
       end;
end;

procedure TForm1.ObjFuncClick(Sender: TObject);
var
  sp: function(val:Integer):string of Object;
begin
  sp:=formsinttostr;
  ExecuteFunction(TMethod(sp));
end;

procedure TForm1.StdFunClick(Sender: TObject);
var
  tm:TMethod;
begin
  tm.code:=@inttostr;
  tm.data:=nil;
  ExecuteFunction(tm);
end;

end.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18888879
huh it's hard to tell which is better, but event oriented solution is more
"delphi like":)

ziolko
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18888918
btw. with event like solution it's very easy to implement different behaviour
for handling "callback":

TCallback = class(TObject)
  function MyOnObjectGoalEventHandler_v1(Sender: TObject;x: Real);
  function MyOnObjectGoalEventHandler_v2(Sender: TObject;x: Real);
  function MyOnObjectGoalEventHandler_v3(Sender: TObject;x: Real);
  function MyOnObjectGoalEventHandler_v4(Sender: TObject;x: Real);
  function MyOnObjectGoalEventHandler_v5(Sender: TObject;x: Real);
end;

or

TCallback_v1 = class(TObject)
  function MyOnObjectGoalEventHandler(Sender: TObject;x: Real);
end;
TCallback_v2 = class(TObject)
  function MyOnObjectGoalEventHandler(Sender: TObject;x: Real);
end;
TCallback_v3 = class(TObject)
  function MyOnObjectGoalEventHandler(Sender: TObject;x: Real);
end;
TCallback_v4 = class(TObject)
  function MyOnObjectGoalEventHandler(Sender: TObject;x: Real);
end;
TCallback_v5 = class(TObject)
  function MyOnObjectGoalEventHandler(Sender: TObject;x: Real);
end;

and hook desired implementation

ziolko.
0
 

Author Comment

by:IgnaceLamine
ID: 18890312
Thanks ziolko, yeah I guess events are the way to go in Delphi. My only issue is that I don't like to use OOP stuff for core mathematical routines (in this case an optimization routine), which I like to keep procedural, but I might change my mind.

Swiatlo, you showed some very interesting stuff with the TMethod type. Not something I would use in practice, but the insight is worth a few points ;)
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …
Suggested Courses

650 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question