bernhard_LA 0 Posted March 10, 2019 (edited) the windows GUI code for a simple INDY 10 tcp demo comes from here : https://github.com/tinydew4/indy-project-demos/tree/master/TCPIP Delphi %26 Indy10 Client Server Demo/1_sample Simple String Exchange I used this code to run the server in a cmd line application, but I fail with the function pointer assignment, what is the correct syntax I need here see the current not working code below program IndyConsoleApp; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, IdContext, IdSync, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, IdGlobal; type OnTCPServerExecutefct = procedure (AContext: TIdContext) of Object ; var IdTCPServer1: TIdTCPServer; TCPServerExecutefct : OnTCPServerExecutefct; procedure ShowStartServerdMessage; begin writeln('START SERVER @' + TimeToStr(now)); end; procedure StopStartServerdMessage; begin writeln('STOP SERVER @' + TimeToStr(now)); end; procedure TCPServerExecute(AContext: TIdContext); var LLine: String; begin TIdNotify.NotifyMethod( ShowStartServerdMessage ); // wrong LLine := AContext.Connection.IOHandler.ReadLn(); writeln(LLine); AContext.Connection.IOHandler.WriteLn('OK'); TIdNotify.NotifyMethod( StopStartServerdMessage ); end; begin IdTCPServer1:=TIdTCPServer.Create; try { TODO -oUser -cConsole Main : Insert code here } IdTCPServer1.Bindings.Add.IP := '127.0.0.1'; IdTCPServer1.Bindings.Add.Port := 6000; IdTCPServer1.OnExecute := TCPServerExecute ; /// wrong ! // TCPServerExecutefct:= assign(TCPServerExecute); readln ; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Edited March 10, 2019 by bernhard_LA Share this post Link to post
Guest Posted March 10, 2019 An easy way would be to create and use a data module, then you can put your Indy components on it and use the IDE designer to write your event handlers. Share this post Link to post
mjustin 23 Posted March 10, 2019 A simple way is to declare a new class, which has a private field IdTCPServer of type TIdCustomTCPServer and a method which matches the signature of the IdTCPServer.OnExecute event handler: TMyClass = class(TObject) private IdTCPServer: TIdCustomTCPServer; procedure MyOnExecute(AContext: TIdContext); public constructor Create; destructor Destroy; override; procedure Run; ... constructor TMyClass.Create; begin IdTCPServer := TIdCustomTCPServer.Create; IdTCPServer.OnExecute := MyOnExecute; end; Instantiate this class and let it create, configure and start the IdTCPServer instance. Share this post Link to post
Martin Wienold 35 Posted March 10, 2019 Indy Callbacks are declared with of object modifier, that means you have to have a method in an object and not a standalone procedure. TCallback1 = procedure (const Arg1: Integer); TCallback2 = procedure (const Arg1: Integer) of object; TCallback3 = reference to procedure (const Arg1: Integer); TCallback1 is used with standalone procedures. TCallback2 is used with methods from objects. TCallback3 can be used with anonymous methods. Share this post Link to post
Remy Lebeau 1393 Posted March 10, 2019 (edited) 5 hours ago, bernhard_LA said: I used this code to run the server in a cmd line application, but I fail with the function pointer assignment, what is the correct syntax I need here Like the events of most other components, the events of Indy components expect class methods, not standalone functions. You could go the way that others have recommended, where creating a TDataModule at design-time and using it at run-time would be the easiest. But, even if you were to simply write a class in code to wrap the events, note that you don't actually need to instantiate such a class at run-time, you can declare its methods with the class directive instead, eg: program IndyConsoleApp; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, IdContext, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, IdGlobal; var IdTCPServer1: TIdTCPServer; procedure ShowStartServerdMessage; begin WriteLn('START SERVER @' + TimeToStr(now)); end; procedure StopStartServerdMessage; begin WriteLn('STOP SERVER @' + TimeToStr(now)); end; type TCPServerEvents = class class procedure OnExecute(AContext: TIdContext); end; class procedure TCPServerEvents.OnExecute(AContext: TIdContext); var LLine: String; begin LLine := AContext.Connection.IOHandler.ReadLn(); writeln(LLine); AContext.Connection.IOHandler.WriteLn('OK'); end; begin try IdTCPServer1 := TIdTCPServer.Create; try with IdTCPServer1.Bindings.Add do begin IP := '127.0.0.1'; Port := 6000; end; IdTCPServer1.OnExecute := TCPServerEvents.OnExecute; IdTCPServer1.Active := True; try ShowStartServerdMessage; Readln; finally IdTCPServer1.Active := False; StopStartServerdMessage; end; finally IdTCPServer1.Free; end; except on E: Exception do WriteLn(E.ClassName, ': ', E.Message); end; end. However, there IS actually a way to use a standalone function instead, but it involves a little trickery using Delphi's TMethod record: program IndyConsoleApp; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, IdContext, IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, IdGlobal; var IdTCPServer1: TIdTCPServer; procedure ShowStartServerdMessage; begin WriteLn('START SERVER @' + TimeToStr(now)); end; procedure StopStartServerdMessage; begin WriteLn('STOP SERVER @' + TimeToStr(now)); end; procedure TCPServerExecute(ASelf: Pointer; AContext: TIdContext); // NOTE THE EXTRA PARAMETER! var LLine: String; begin LLine := AContext.Connection.IOHandler.ReadLn(); WriteLn(LLine); AContext.Connection.IOHandler.WriteLn('OK'); end; var ExecuteFct: TMethod; begin try IdTCPServer1 := TIdTCPServer.Create; try with IdTCPServer1.Bindings.Add do begin IP := '127.0.0.1'; Port := 6000; end; ExecuteFct.Data := nil; // or anything you want to pass to the ASelf parameter... ExecuteFct.Code := @TCPServerExecute; IdTCPServer1.OnExecute := TIdServerThreadEvent(ExecuteFct); IdTCPServer1.Active := True; try ShowStartServerdMessage; Readln; finally IdTCPServer1.Active := False; StopStartServerdMessage; end; finally IdTCPServer1.Free; end; except on E: Exception do WriteLn(E.ClassName, ': ', E.Message); end; end. Edited March 10, 2019 by Remy Lebeau 2 1 Share this post Link to post