开发者

Reading C structures with "union" types from C# with PInvoke

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 someth开发者_如何学Pythoning different?


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
{
    //...
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜