0

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 | :) !!

1

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.