简体   繁体   中英

How to convert C# Struct to Byte Array

I have a structure which I want to send to a TCP client throught TCP protocol so I want to assign or copy this struct data to byte array:

struct StartReadXML
   {
       public int CmdID;//3
       public char[] CmdName;//ReadXML
       public char[] Description;//Other data

   };

here am assigning data to struct data members as below :

StartReadXML startXML=new StartReadXML();
startXML.CmdID = 3;
startXML.CmdName = "sreedhar".ToCharArray();
startXML.Description = "Kumar".ToCharArray();

Now, I want it to be assigned to a byte array. Which am doing using marshalling as below:

int sizestartXML = Marshal.SizeOf(startXML);//Get size of struct data
byte[] startXML_buf = new byte[sizestartXML];//byte array & its size
IntPtr ptr = Marshal.AllocHGlobal(sizestartXML);//pointer to byte array
Marshal.StructureToPtr(startXML, ptr, true);
Marshal.Copy(ptr, startXML_buf, 0, sizestartXML);
Marshal.FreeHGlobal(ptr);

//Sending struct data  packet
stm.Write(startXML_buf, 0, startXML_buf.Length);//Modified

But, it fails at Structuretoptr conversion method. Please help in transferring the struct data as bytes for which am using above steps. Thanks in advance Smile | :) !!

You cannot call StructureToPtr on arrays of variable size.

What this boils down to is that unless you know the size of CmdName and declare it - if it would be for example, 20 chars in size, like so:

public fixed char[] CmdName[20];

You will be greeted with an exception from the Marshal saying that your structure is either non-blittable or no meaningful size can be obtained.

This is a requirement the CLR imposes, and you can not work around.

An alternative method would be to use the Convert class or a serializer to convert the members of your struct manually, but unless you know the size of those arrays up front, you won't be able to use StructureToPtr - the same goes for the string type, as I'm assuming that's what your char array will contain.

Consider using a MemoryStream and writing values to the stream, and sending the contents of the stream using stream.ToArray() instead.

Considering that you can't simply convert to binary a struct, use for example:

class StartReadXML
{
    public int CmdID;//3
    public string CmdName;//ReadXML
    public string Description;//Other data
}

Then:

var srx = new StartReadXML();
srx.CmdID = 3;
srx.CmdName = "sreedhar";
srx.Description = "Kumar";

// Example of how to Write to byte[] buffer

byte[] buffer;

using (var ms = new MemoryStream())
{
    using (var bw = new BinaryWriter(ms, Encoding.UTF8))
    {
        bw.Write(srx.CmdID);
        bw.Write(srx.CmdName);
        bw.Write(srx.Description);
    }

    buffer = ms.ToArray();
}

// Example of how to Read from byte[] buffer

var srx2 = new StartReadXML();

using (var ms = new MemoryStream(buffer))
{
    using (var br = new BinaryReader(ms, Encoding.UTF8))
    {
        srx2.CmdID = br.ReadInt32();
        srx2.CmdName = br.ReadString();
        srx2.Description = br.ReadString();
    }
}

Note that here I'm working with a "variable length" packet: the length of CmdName and Description aren't fixed (and BinaryWriter / BinaryReader handle this by prepending the length of the string).

The opposite is when you have a packet of fixed length, with fixed-length strings. That requires a totally different handling.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM