Recent

Author Topic: Callback function in communications class - how?  (Read 1112 times)

BosseB

  • Sr. Member
  • ****
  • Posts: 468
Callback function in communications class - how?
« on: July 07, 2020, 10:22:47 pm »
I am working on a socket server function and I want to keep the data interpretation out of this object. It should only handle client connections and telegram reception and dispatching.

So I figured I could do something like this:

In the class file:

Code: Pascal  [Select][+][-]
  1. {$mode Delphi}
  2. .....
  3. type
  4.  
  5.   TProcessPacket = procedure (Sender: TObject; Data: string; var Response: string);
  6.  
  7.   TRemoteServer = class(TObject)
  8.   private
  9.     FServer: TIdTCPServer;
  10.     FClientPort: word;
  11.     FProcessData: TProcessPacket;
  12.     ....
  13.   public
  14.     constructor Create;
  15.     destructor Destroy; override;
  16.     property ProcessData: TProcessPacket read FProcessData write FProcessData;
  17.     ....
  18. end;
  19.  
  20. procedure TRemoteServer.ServerExecute(AContext: TIdContext);
  21. var
  22.   msg, reply, cmd: string;
  23.   i, n: integer;
  24. begin
  25.   ...
  26.   msg := AContext.Connection.IOHandler.ReadLn(ETX);
  27.   if Pos(STX, msg) = 1 then //Remove leading STX
  28.     Delete(msg, 1, 1);
  29.   if FProcessData <> nil then  // <== ERROR HERE!!!
  30.     FProcessData(AContext, msg, reply)
  31.   else
  32.     reply := 'ERROR';
  33.   AContext.Connection.IOHandler.Write(reply);
  34. end;

In the main project file:

Code: Pascal  [Select][+][-]
  1. {$mode Delphi}
  2.  
  3. var
  4.   RemoteSrv: TRemoteServer;
  5.   ch: char;
  6.  
  7.  
  8. procedure Respond(Sender: TObject; Data: string; var Response: string);
  9. var
  10.   reply: string;
  11.   n: integer;
  12. begin
  13.   if Pos('LOGIN', Data) = 1 then
  14.     reply := 'LOGIN' + TAB + 'OK '
  15.   else
  16.   begin
  17.     n := Pos(TAB, Data);
  18.     if n <1 then
  19.       reply := Data
  20.     else
  21.       reply := Copy(Data, 1, n-1) + TAB + 'ERR';
  22.   end;
  23.   Response := reply;
  24. end;
  25.  
  26. begin
  27.   RemoteSrv := TRemoteServer.Create; //Uses default port 23500
  28.   RemoteSrv.ProcessData := Respond; //Assign the processing function so the object can call it
  29.   try
  30.   ....
  31.  

But it errors out on the line indicated above with the following message:
Code: Pascal  [Select][+][-]
  1. remoteserver.pas(160,19) Error: Wrong number of parameters specified for call to "<Procedure Variable>"

I am assigning the procedure to the object property so it can be used in the code and I need to do an error check so that the function is not accidentally executed if it was not assigned....

Obviously I am doing something wrong when I check if the FProcessData  field is assigned (not NIL).
How am I supposed to do this in Lazarus/FPC?
--
Bo Berglund
Sweden

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Callback function in communications class - how?
« Reply #1 on: July 07, 2020, 10:43:48 pm »
I don't know what you expect, in your example you are assigning the callback so of course it's going to be valid..

 Did I miss something ?

 
The only true wisdom is knowing you know nothing

BosseB

  • Sr. Member
  • ****
  • Posts: 468
Re: Callback function in communications class - how?
« Reply #2 on: July 08, 2020, 12:05:56 am »
It complains about this line of code:

Code: Pascal  [Select][+][-]
  1.   if FProcessData <> nil then  // <== ERROR HERE!!!
  2.     FProcessData(AContext, msg, reply)
  3.  

With this error message:
Code: Pascal  [Select][+][-]
  1. remoteserver.pas(160,19) Error: Wrong number of parameters specified for call to "<Procedure Variable>"

Obviously instead of checking if the FProcessData field contains a valid assignment (non-NIL) the compiler tries to execute the procedure FProcessData, to compare the result of that execution with NIL and this then is an erroneous call to FProcessData, hence the error.

My question is simply put:
How can I check if FProcessData has been set before I call it?
--
Bo Berglund
Sweden

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Callback function in communications class - how?
« Reply #3 on: July 08, 2020, 12:27:34 am »
There are two things you can try...

 first one would be using the "Assigned" if Assigned(F.....) Then....

 The other is to type cast it..

 If Pointer(Fxxxxx) <> Nil Then ….


 
The only true wisdom is knowing you know nothing

BosseB

  • Sr. Member
  • ****
  • Posts: 468
Re: Callback function in communications class - how?
« Reply #4 on: July 08, 2020, 12:28:41 am »
Quote
My question is simply put:
How can I check if FProcessData has been set before I call it?

Found the answer by checking old code I have in another project:

Code: Pascal  [Select][+][-]
  1.   if Assigned(FProcessData) then
  2.     FProcessData(AContext, msg, reply)
  3.   else
  4.     reply := 'ERROR';
  5.  

I have previously tried
Code: Pascal  [Select][+][-]
  1. if IsAssigned(FProcessData) then

which did not work of course....
--
Bo Berglund
Sweden

 

TinyPortal © 2005-2018