Search code examples
c#structcompact-frameworkstructlayout

Is there an alternative for StructLayout "Pack" attribute in Compact Framework?


I would like to do the following:

  [StructLayout(LayoutKind.Sequential, Pack = 1)]
  public struct SomeStruct
  {
     public byte  SomeByte;
     public int   SomeInt;
     public short SomeShort;
     public byte  SomeByte2;
  }

Is there an alternative since Pack is not supported in the compact framework?

Update: Explicitly setting up the structure and giving FieldOffset for each does not work either as it does not affect how the struct is packed

Update2: If you try the following, the CF program wont even run because of how the structure is packed:

[StructLayout(LayoutKind.Explicit, Size=8)]
public struct SomeStruct
{
   [FieldOffset(0)]
   public byte SomeByte;
   [FieldOffset(1)]
   public int SomeInt;
   [FieldOffset(5)]
   public short SomeShort;
   [FieldOffset(7)]
   public byte SomeByte2;
}

I know it seems hard to believe, but if you try it you will see. Add it to a CF project and try to run it and you will get a TypeLoadException. Changing the offsets to 0,4,8,10 respectively and it will work (but the size ends up being 12).

I was hoping maybe someone had a solution using reflection maybe to marshal the size of each of the field types individually (something involving recursion to handle structs within structs or arrays of types).


Solution

  • This probably isn't the type of answer you're looking for, but I'll post it anyway for the hell of it:

    public struct SomeStruct
    {
        public byte SomeByte;
        public int SomeInt;
        public short SomeShort;
        public byte SomeByte2;
    
    
        public byte[] APIStruct
        {
            get
            {
                byte[] output = new byte[8];
                output[0] = this.SomeByte;
                Array.Copy(BitConverter.GetBytes(this.SomeInt), 0,
                    output, 1, 4);
                Array.Copy(BitConverter.GetBytes(this.SomeShort), 0,
                    output, 5, 2);
                output[7] = this.SomeByte2;
                return output;
            }
            set
            {
                byte[] input = value;
                this.SomeByte = input[0];
                this.SomeInt = BitConverter.ToInt32(input, 1);
                this.SomeShort = BitConverter.ToInt16(input, 5);
                this.SomeByte2 = input[7];
            }
        }
    }
    

    Basically it does the packing/unpacking itself in the APIStruct property.