2

I am trying to marshal a struct to a byte[] and then back again but am getting an ArgumentOutOfRangeException when marshaling back to struct. Here is the code:

public struct Response
{
    CommandNumber Command;
    ushort EstimatedRoundTripDuration;
}

protected TStruct ByteArrayToStruct<TStruct>(byte[] data) where TStruct : struct
{
    TStruct resp = new TStruct();
    int size = Marshal.SizeOf(resp);
    IntPtr ptr = Marshal.AllocHGlobal(size);

    try
    {
        Marshal.Copy(data, 0, ptr, size);
        Marshal.PtrToStructure(ptr, resp);

        return resp;
    }
    finally
    {
        Marshal.FreeHGlobal(ptr); //cleanup just in case
    }
}

The problem seems to be that sizeof(Response) is 3, whilst Marshal.SizeOf(resp) is 4. I understand that these can be and are expected to be different but im using fairly basic types for this struct. Can anyone shed any light on why the sizes are different?

Gusdor
  • 14,001
  • 2
  • 52
  • 64
  • 2
    They can be and are expected to be different. Answered [here](http://stackoverflow.com/questions/3361986/how-to-check-the-number-of-bytes-consumed-by-my-structure/3362736#3362736). – Hans Passant Sep 17 '13 at 12:53

1 Answers1

2

I assume that CommandNumber is one byte. As I recall, the interop layer likes to align data fields. So your EstimatedRoundTripDuration will be aligned to the next even address, leaving one byte of padding. So it would look like this:

Command: 1 byte
padding: 1 byte
EstimatedRoundTripDuration: 1 byte

You can change the marshaling behavior with the StructLayout attribute:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct Response
{
    CommandNumber Command;
    ushort EstimatedRoundTripDuration;
}
Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • I forgot to change the enumeration to byte, but yes it is 8bit. I'm assuming this 'even byte' padding is based upon the word size of my system (64bit) - is that correct? The StructLayout attribute alone did not help. I have to change the Pack property to 1. – Gusdor Sep 17 '13 at 13:02
  • @Gusdor: The "even byte" padding will occur on a 32-bit machine, as well. I don't know all the rules of the default packing. You'll have to look up the documentation for Pack, and possibly do a bit more research than that. – Jim Mischel Sep 17 '13 at 14:27