I'm trying to bring to managed side (C#) a structure built in C.
Let's assume this structure (C code):
typedef struct S{
int i;
union{
TypeA a;
TypeB b;
TypeC c;
}uni;
} S;
Now, i create the C# wrapper classes:
[StructLayout(LayoutKind.Explicit)]
public class S
{
[FieldOffset(0)]
public int i;
[FieldOffset(4)]
public TypeA a;
[FieldOffset(4)]
public TypeB b;
[FieldOffset(4)]
public TypeC c;
}
And I have a PInvoke method to get the S object:
(C's implementation create and return a S structure with a TypeA in union field)
[DllImport("Library.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.S)]
public static extern S getUnionStruct();
Somewhere in main function, I do:
S s = getUnionStruct();
Console.WriteLine("unions type: {0}",(S.a).GetType());
The result is "AssembleName.TypeC" (???)
.net Framework is assuming the TypeC because that was the last declared. I also notice that if the size of TypeC is smaller than TypeA I get unable to read all the TypeA fields..
Is this a bug from .net or I should be doing something different?
Both structure and union are user-defined data types in C programming that hold multiple members of different data types. Structures are used when we need to store distinct values for all the members in a unique memory location, while unions help manage memory efficiently.
C - Typedef. C - Input & Output. C - File I/O. C - Preprocessors. C - Header Files.
A structure can be nested inside a union and it is called union of structures. It is possible to create a union inside a structure.
The problem is about using reference types to wrap the unmanaged types.
When the CLR executes the "GetType" method, it uses a virtual table which only can contain one type that was successively overridden in declaration. The last declared field wins (TypeC in this case)
Switching the "class" to "struct" resolves the problem.
[StructLayout(LayoutKind.Explicit)]
public struct S
{
[FieldOffset(0)]
public int i;
[FieldOffset(4)]
public TypeA a;
[FieldOffset(4)]
public TypeB b;
[FieldOffset(4)]
public TypeC c;
}
[StructLayout(LayoutKind.Sequencial)]
public struct TypeA
{
//...
}
[StructLayout(LayoutKind.Sequencial)]
public struct TypeB
{
//...
}
[StructLayout(LayoutKind.Sequencial)]
public struct TypeC
{
//...
}
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