1

I have been working on some interface which has define a buffer of data, and it can be convert to related data structure in c union as below,

union DATA_STRUCTURE {
    uint8_t buffer[BUFFER_SIZE];
    A_STRUCT a;
    B_STRUCT b;
}; 

I can put the received data into buffer, and read the data using a or b according to the data type defined somewhere in buffer.

And now, I'm going to rewrite the interface program in c#, I can't find union like syntax in c#, and I found that there are many similar post on this topic, it is suggested to implement using FieldOffset as below,

  [StructLayout(LayoutKind.Explicit)]
  struct MyUnion
  {
    [FieldOffset(0)] int I;
    [FieldOffset(0)] float F;
  }

I just try to define the struct as below,

  [StructLayout(LayoutKind.Explicit, Size = 16)]
  struct MyUnion
  {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    [FieldOffset(0)] public byte[] buffer;
    [FieldOffset(0)] public A_STRUCT a;
    [FieldOffset(0)] public B_STRUCT b;
  }
  MyUnion data;

But I cannot fill the data to buffer by the statement like data.buffer[0] = x; It will show the error "Use of possibly unassigned field 'buffer'". Moreover, even I can put the value to buffer, it seems that the same error will returned if I try to access the data via a or b.

I have also try using pointer approach with unsafe option, but it seems that I still cannot get the address for a unsafe struct, the following statement is not allowed,

  byte *ptr = (byte *) &data;
  byte *ptr = data.buffer;
  byte *ptr = &data.buffer[0];

Maybe I still missed something for using unsafe keyword.

May I know if there has any way to implement the union struct in C# for above situation?

Thanks a lot.

James MA
  • 323
  • 5
  • 14

1 Answers1

1

Since the array is a managed object (not a struct), I don't think you can really play union style tricks with it.

I'd just work with a plain byte[] up until I'm ready to convert, then get an IntPtr from the array (via fixed, probably) and then use Marshal.PtrToStructure to obtain A_STRUCT or B_STRUCT. Of course, this is more work if your access patterns are more like:

  • treat it as an array
  • treat it as an A_STRUCT
  • treat it as an array
  • treat it as a B_STRUCT
Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
  • Thanks for the suggestion. By using IntPtr with Marshal.PtrToStructure can help to retrieve the data from buffer using the structure. However, PtrToStructure will create a copy of data, instead of pointing to the original memory location. As the original buffer will be used for return, so it need to convert the data back to the buffer. It need to copy the content to IntPtr by Marshal.StructureToPtr, then use Marshal.Copy to fill the content back to buffer. By using some Marshal operation, I can have similar result as before. Thanks a lot. – James MA Oct 11 '18 at 02:50