I have a C++ struct that looks like this:
struct unmanagedstruct
{
int flags;
union
{
int offset[6];
struct
{
float pos[3];
float q[4];
} posedesc;
} u;
};
And I'm trying to Marshal it like so in C#:
[StructLayout(LayoutKind.Explicit)]
public class managedstruct {
[FieldOffset(0)]
public int flags;
[FieldOffset(4), MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 6)]
public int[] offset;
[StructLayout(LayoutKind.Explicit)]
public struct posedesc {
[FieldOffset(0), MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3)]
public float[] pos;
[FieldOffset(12), MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4)]
public float[] q;
}
[FieldOffset(4)]
public posedesc pose;
}
However, when I try loading data into my struct only the first 3 elements of the offset array are there (the array's length is 3). I can confirm that their values are correct - but I still need the other 3 elements. Am I doing something obviously wrong?
I'm using these functions to load the struct:
private static IntPtr addOffset(IntPtr baseAddress, int byteOffset) {
switch (IntPtr.Size) {
case 4:
return new IntPtr(baseAddress.ToInt32() + byteOffset);
case 8:
return new IntPtr(baseAddress.ToInt64() + byteOffset);
default:
throw new NotImplementedException();
}
}
public static T loadStructData<T>(byte[] data, int byteOffset) {
GCHandle pinnedData = GCHandle.Alloc(data, GCHandleType.Pinned);
T output = (T)Marshal.PtrToStructure(addOffset(pinnedData.AddrOfPinnedObject(), byteOffset), typeof(T));
pinnedData.Free();
return output;
}
Loading example:
managedstruct mystruct = loadStructData<managedstruct>(buffer, 9000);
Let me know if you need more information.
I'm not 100% sure about this but I believe that the Union means that the same memory is used for both members. In the case of the C++ structure, an int[] or a posedesc structure. So the size of the structure will be sizeof(int) + sizeof(posedisc). Meaning, Union doesn't mean you'll have both an int[] and a posedisc you'll have shared memory that can be either of those types in C++ land but only one or the other in managed land.
So I think you probably need two managed structures, one that has offset and one that has posedisc. You can pick one or the other in your call to LoadStruct. Optionally you could create a byte[] field and have calculated properties that convert those bytes into the desired types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With