Superjet100
Superjet100

Reputation: 129

Delphi records conversion to C# struct and write to socket

I have following Delphi code:

type
   RegbusReq2=packed record 
     Funct:char;             
     Device:char;           
     Device1:char;
     Starting:integer;       
     Quantity:smallint;      
     _CRC:Word;              //CRC
     stroka:char;          
   end;

   type                         
     crcReg=packed record
     buf:array[0..2] of byte;
     value:array[0..5] of byte;
   end;

   type                          
   myRB=record                      
   case byte of
    0:(data:RegbusReq2);
    1:(Buff:crcReg);
   end;
...
procedure TForm1.Button3Click(Sender: TObject);
var
  DataReq:myRB;
  Output:array[1..15] of Byte;
  i:integer;
  nomP:string;
  st:string;
begin
cs1.Address:=edit5.Text;  
 cs1.Port := 6001;
typecon:=2;

DataReq.data.Funct:=chr(63);    
DataReq.data.Device:=chr(48);     
DataReq.data.Device1:=chr(49);    
DataReq.data.Starting:=768;     
DataReq.data.Quantity:=7;      
DataReq.data._CRC:=CRC2(@DataReq.Buff.value,6);      
  memo1.Lines.Add(IntToStr(DataReq.data._CRC));
DataReq.data.stroka:=chr(13);             
application.ProcessMessages();
  cs1.Active:=true;
  cs1.Socket.SendBuf(DataReq.data,SizeOf(DataReq.data));
  application.ProcessMessages();
  cs1.Socket.ReceiveBuf(output,SizeOf(output));         
  application.ProcessMessages();
  cs1.Active:=false;
  application.ProcessMessages();

if output[1]<>62 then begin
  showmessage('îøèáêà ñâÿçè');
  exit;
end;
  for i:=10 to 15 do
  begin
    nomp:= nomp + chr(Output[i]);
    st:=st + '_' + inttostr(output[i]);
  end;
  memo1.Lines.Add(inttostr(sizeof(DataReq.data)));
  memo1.Lines.Add(st);
  memo1.Lines.Add(DataReq.data.Funct);
  form1.Caption:=nomp;
  Button1.Enabled:=true;
end;

This code is working and in Delphi I watch: http://i48.tinypic.com/ei6ph5.png

In C# I've started with following code of struct:

[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Size=12)]
        struct RegBusRec
        {
            [FieldOffset(0)]
            public char Funct;
            [FieldOffset(1)]
            public char Device;
            [FieldOffset(2)]
            public char Device1;
            [FieldOffset(6)]
            public uint Starting;
            [FieldOffset(8)]
            public ushort Quantity;
            [FieldOffset(10)]
            public uint _CRC;
            [FieldOffset(11)]
            public char Message;
        }

And I try to convert srtuct to byte array with code:

public static byte[] Serialize(object obj)
        {
            Type objectType = obj.GetType();
            int objectSize = Marshal.SizeOf(obj);
            IntPtr buffer = Marshal.AllocHGlobal(objectSize);
            Marshal.StructureToPtr(obj, buffer, false);
            byte[] array = new byte[objectSize];
            Marshal.Copy(buffer, array, 0, objectSize);
            Marshal.FreeHGlobal(buffer);
            return array;
        }

And send it:

System.Net.Sockets.TcpClient cl = new System.Net.Sockets.TcpClient();
            cl.Connect(IPAddress.Parse("xxx.xxx.xxx.xxx"), 6001);
if (cl.Connected)
            {
RegBusRec req2 = new RegBusRec();
                req2.Funct = '?';
                req2.Device = '0';
                req2.Device = '1';
                req2.Starting = 768;
                req2.Quantity = 7;
                req2.Message = '\r';
byte[] data = Serialize(req2);
cl.Client.Send(data);
                cl.Client.Receive(output);
if (output[0] != 62)
                {
                    Console.WriteLine("Connection error!");
                    Console.ReadLine();
                }
}

But I get wrong message from device. Need to correct convert Delphi code to C#. Thanks in advance.

Upvotes: 1

Views: 1768

Answers (1)

David Heffernan
David Heffernan

Reputation: 612794

Your struct is wrong. It should be:

[StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
struct RegBusRec
{
    public char Funct;
    public char Device;
    public char Device1;
    public int Starting;
    public short Quantity;
    public ushort _CRC;
    public char Message;
}

Delphi Integer matches C# int. Delphi Smallint matches C# short. Delphi Word matches C# ushort.

Your use of explicit layout just makes life hard for you. Use sequential and the Pack attribute to simplify matters.

In the code where you initialise a struct you write:

req2.Device = '0';
req2.Device = '1';

I expect that you meant to write

req2.Device = '0';
req2.Device1 = '1';

I've not checked anything else, and there may be other errors that I have not found. If I were you I would add diagnostics code to emit byte by byte your serialized struct so that you can be sure that you are serializing it correctly.

Upvotes: 5

Related Questions