2010-03-05 14 views
7

estoy tratando de llevar al equipo dirigido (C#) una estructura construida en C.estructuras de lectura C con tipos de "unión" de C# con PInvoke

Supongamos esta estructura (código C):

typedef struct S{ 
    int i; 
    union{ 
     TypeA a; 
     TypeB b; 
     TypeC c; 
    }uni; 
} S; 

Ahora, i crear las clases contenedoras C#:

[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; 
} 

y tengo un método PInvoke para obtener el objeto S:
(aplicación de C crear y devolver una S st ructure con un TypeA en el campo de unión)

[DllImport("Library.dll", CharSet = CharSet.Auto)] 
[return: MarshalAs(UnmanagedType.S)] 
public static extern S getUnionStruct(); 

En algún lugar de la función principal, que hago:

S s = getUnionStruct(); 
Console.WriteLine("unions type: {0}",(S.a).GetType()); 

El resultado es (???)

Net Framework "AssembleName.TypeC" está asumiendo el TypeC porque ese fue el último declarado. También observo que si el tamaño de TypeC es más pequeño que TypeA, no puedo leer todos los campos TypeA.

¿Este es un error de .net o debería estar haciendo algo diferente?

Respuesta

7

El problema consiste en utilizar tipos de referencia para ajustar los tipos no administrados. Cuando CLR ejecuta el método "GetType", utiliza una tabla virtual que solo puede contener un tipo que se anuló sucesivamente en la declaración. El último campo declarado gana (TypeC en este caso)
Cambiar la "clase" a "struct" resuelve el problema.

[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 
{ 
    //... 
} 
Cuestiones relacionadas