Indy10 TCPServer (Delphi) -> TCPClient (Lazarus) record sending issue lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- swierzbicki · 2014-08-20 16:31 Hello, I've an issue while sending a record from a Delphi TCP Server to an Lazarus TCP Client. Lazarus is throwing SIGSEGV exception when I try to read any fields from my record. I don't know what to do as everything is well working under Delphi. Does anybody know where is my problem ? Here is the Record structure used to be exchanged between my client and server : Code: [Select]type   TMultiCN =  Record     Date: Tdatetime;     Poste: String;     Pilote1:String;     Pilote2: String;     OrdreFrabication: String;     Evenement: String;     Piquage:String;     Point: Double;     cadencemoyenne: Double;     cadencemaxi: Double;     longueur: Double;   End; Here is the client code (that works under Delphi but fails with Lazarus) Code: [Select]var   MultiCNData: TMultiCN;   Buffer: TIdBytes; begin   IdTCPClient1.Connect;   try     IdTCPClient1.GetResponse('200');     if IdTCPClient1.SendCmd('OPERATION') <> 100 then       raise Exception.Create(IdTCPClient1.LastCmdResult.Text.Text);     IdTCPClient1.IOHandler.ReadBytes(Buffer, SizeOf(MultiCNData));     BytesToRaw(Buffer, MultiCNData, SizeOf(MultiCNData));     mmLogs.Lines.Add('-----');     mmLogs.Lines.Add(DateTimeToStr(MultiCNData.Date)); // All attempt to use the record fields leads to an     mmLogs.Lines.Add(MultiCNData.Poste);                        // SIGSEGV exception !   finally     IdTCPClient1.Disconnect();     if IdTCPClient1.IOHandler <> nil then       IdTCPClient1.IOHandler.InputBuffer.Clear;   end; Here is the server code (compiled with Delphi) Code: [Select]var   MultiCNData: TMultiCN;   Buffer: TIdBytes;   LReply: TIdReplyRFC; begin   try     MultiCNData.Date := Now;     MultiCNData.Poste := 'PicPic6';     MultiCNData.Pilote1 := 'Pilote1';     MultiCNData.Pilote1 := 'Pilote2';     MultiCNData.OrdreFrabication := '012365';     MultiCNData.Evenement := 'Démarrage';     MultiCNData.Piquage := 'Fichier.cnc';     MultiCNData.Point := 2115;     MultiCNData.cadencemoyenne := 45.55;     MultiCNData.cadencemaxi := 78.1;     MultiCNData.longueur := 1.8;     LReply := TIdReplyRFC.Create(nil);     try       LReply.SetReply(100, 'ready to send you data');       ASender.Context.Connection.IOHandler.Write(LReply.FormattedReply);     finally       FreeAndNil(LReply);     end;     Buffer := RawToBytes(MultiCNData, SizeOf(MultiCNData));     ASender.Context.Connection.IOHandler.Write(Buffer);   except     on E: Exception do     Begin       ASender.Reply.SetReply(500, E.message);     end;   end; end; Ps : I'm using the last SVN Indy version / Unicode Delphi version. I've already tried to modify my record structure from string to ansistring fields type... ---------------------------------------------------------------------- rvk · 2014-08-20 17:00 Quote from: swierzbicki on August 20, 2014, 06:31:01 pmI don't know what to do as everything is well working under Delphi. ... Here is the Record structure used to be exchanged between my client and server : Are you using Ansistrings? What is at the top of your unit? Do you see a {$H-} or {$H+}? And are you using {$mode delphi} or {$mode objfpc}? If you're using a different string-type than Delphi your record- structures won't match. ---------------------------------------------------------------------- taazz · 2014-08-20 17:40 1) have you actually seen what rawtobytes does? 2) you do understand that the string data type is what in java is known as a reference type right? which in sort means that the fields Poste, Pilote1, Pilote2, etc are nothing more than pointers to the actual data and those data are not continuous in memory right? 3) which version of delphi are you using? You do know that after D2009 the string datatype is alias for unicodestring while in fpc is still alias for ansistring? in general, try to convert all string types to short strings ee string[255] instead or even to array[1..4096] of unicodechar/ansichar etc. at least then the rawtobytes function should always work correctly. keep in mind that from some kind of very good luck you did not have problems so far in the delphi to delphi communication and it is a trap waiting to cut of what ever gets cot in it, so you need to either write your own rawtobytes and bytestoraw routines or change the record something more linear as described above. ---------------------------------------------------------------------- swierzbicki · 2014-08-21 15:55 Hello, My problem is that I've sent a pointer value. I needed to serialyze my String and Double types. Remy Lebeau helped me on this. For those interrested, here is the working code : Client TCP  code : Code: [Select]    var       MultiCNData: TMultiCN;       function ReadString: String;       begin         Result := IdTCPClient1.IOHandler.ReadString(IdTCPClient1.IOHandler.ReadLongInt, encUTF8);       end;       function ReadDouble: Double;       var         Tmp: TIdBytes;       begin         IdTCPClient1.IOHandler.ReadBytes(Tmp, SizeOf(Double));         BytesToRaw(Tmp, Result, SizeOf(Double));       end;       procedure ReadMultiCN(var Data: TMultiCN);       begin         Data.Date := ReadDouble;         Data.Poste := ReadString;         Data.Pilote1 := ReadString;         Data.Pilote2 := ReadString;         Data.OrdreFrabication := ReadString;         Data.Evenement := ReadString;         Data.Piquage := ReadString;         Data.Point := ReadDouble;         Data.cadencemoyenne := ReadDouble;         Data.cadencemaxi := ReadDouble;         Data.longueur := ReadDouble;       end;     begin       IdTCPClient1.Connect;       try         IdTCPClient1.GetResponse(200);         IdTCPClient1.SendCmd('OPERATION', 100);         ReadMultiCN(MultiCNData);         mmLogs.Lines.Add('-----');         mmLogs.Lines.Add(DateTimeToStr(MultiCNData.Date));         mmLogs.Lines.Add(MultiCNData.Poste);       finally         IdTCPClient1.Disconnect;         if IdTCPClient1.IOHandler <> nil then           IdTCPClient1.IOHandler.InputBuffer.Clear;       end;    end; TCP CMD Server code Code: [Select]    var       MultiCNData: TMultiCN;       procedure SendString(const Value: String);       var         Tmp: TIdBytes;       begin         Tmp := ToBytes(Value, encUTF8);         ASender.Context.Connection.IOHandler.Write(Length(Tmp));         ASender.Context.Connection.IOHandler.Write(Tmp);       end;       procedure SendDouble(Value: Double);       begin         ASender.Context.Connection.IOHandler.Write(RawToBytes(Value, SizeOf(Double)));       end;       procedure SendMultiCN(const Data: TMultiCN);       begin         ASender.Context.Connection.IOHandler.WriteBufferOpen;         try           SendDouble(Data.Date);           SendString(Data.Poste);           SendString(Data.Pilote1);           SendString(Data.Pilote1);           SendString(Data.OrdreFrabication);           SendString(Data.Evenement);           SendString(Data.Piquage);           SendDouble(Data.Point);           SendDouble(Data.cadencemoyenne);           SendDouble(Data.cadencemaxi);           SendDouble(Data.longueur);           ASender.Context.Connection.IOHandler.WriteBufferClose;         except           ASender.Context.Connection.IOHandler.WriteBufferCancel;           raise;         end;       end;     begin       MultiCNData.Date := Now;       MultiCNData.Poste := 'PicPic6';       MultiCNData.Pilote1 := 'Pilote1';       MultiCNData.Pilote1 := 'Pilote2';       MultiCNData.OrdreFrabication := '012365';       MultiCNData.Evenement := 'Démarrage';       MultiCNData.Piquage := 'Fichier.cnc';       MultiCNData.Point := 2115;       MultiCNData.cadencemoyenne := 45.55;       MultiCNData.cadencemaxi := 78.1;       MultiCNData.longueur := 1.8;       ASender.Reply.SetReply(100, 'ready to send you data');       ASender.SendReply;       SendMultiCN(MultiCNData);     end;