2009-07-27 11 views
8

Sto cercando di creare la seguente struttura:correttamente allineati o sovrapposte da un errore campo non oggetto

[StructLayout(LayoutKind.Explicit, Size=14)] 
    public struct Message 
    { 
     [FieldOffset(0)] 
     public ushort X; 
     [FieldOffset(2)] 
     [MarshalAs(UnmanagedType.ByValArray, SizeConst=5)] 
     private ushort[] Y; 
     [FieldOffset(12)] 
     public ushort Z; 
    } 

e ottengo il seguente errore:

Impossibile caricare il tipo 'Messaggio' da assembly perché contiene un campo oggetto con offset 4 che è allineato o sovrapposto in modo non corretto da un campo non oggetto.

Qualcuno sa perché questo sta causando un errore?

Nota: non riesco a utilizzare Pack perché sto lavorando con il framework compatto. Grazie.

risposta

8

CF Marshaler non è così bravo in questo tipo di cose e quello che si sta tentando non è supportato. Il problema è che sa che il primo elemento non è allineato, ma sembra non capire che ogni elemento dell'array sarebbe anche non allineato.

È possibile vedere il comportamento funziona in questo esempio:

[StructLayout(LayoutKind.Explicit, Size = 14)] 
public struct Message 
{ 
    [FieldOffset(0)] 
    public ushort X; 

    [FieldOffset(2)] 
    private ushort Y1; 

    [MarshalAs(UnmanagedType.LPArray)] 
    [FieldOffset(4)] 
    private ushort[] Y2; 

    [FieldOffset(12)] 
    public ushort Z; 
} 

Per questo tipo di struttura, non ho mai lasciato il gestore di marshalling cercare di gestire ciascuno dei membri in ogni caso. La struttura è piccola, quindi rompere ogni singolo elemento in questo modo:

[StructLayout(LayoutKind.Explicit, Size = 14)] 
public struct Message 
{ 
    [FieldOffset(0)] 
    public ushort X; 

    [FieldOffset(2)] 
    private ushort Y1; 

    [FieldOffset(4)] 
    private ushort Y2; 

    [FieldOffset(6)] 
    private ushort Y3; 

    [FieldOffset(8)] 
    private ushort Y4; 

    [FieldOffset(10)] 
    private ushort Y5; 

    [FieldOffset(12)] 
    public ushort Z; 
} 

o utilizzare un simulato "unione" come questo:

public struct Y 
{ 
    public ushort a; 
    public ushort b; 
    public ushort c; 
    public ushort d; 
    public ushort e; 
} 

[StructLayout(LayoutKind.Explicit, Size = 14)] 
public struct Message 
{ 
    [FieldOffset(0)] 
    public ushort X; 

    [FieldOffset(2)] 
    private Y Y; 

    [FieldOffset(12)] 
    public ushort Z; 
} 
+0

Ok, quindi la risposta più semplice è nel commento qui sotto: Le matrici devono essere DWORD allineate nel CF – SwDevMan81

+0

@ctacke: Potrebbe farmi riferimento a un riferimento che contiene informazioni dettagliate su Marshaler CF (ad esempio che gli array devono essere DWORD allgned)? – Odrade

+0

@david: non ne conosco uno. Tutto quello che so del marshaler e le sue capacità (o la sua mancanza) derivano dall'incontro e dalle conversazioni con il team CF, insieme a anni di esperienza nel tentativo di farlo fare ciò che voglio. – ctacke

1

Il problema si verifica perché la matrice si sovrappone a "X". ulong, in C#, è UInt64 (in C++, ulong è UInt32), quindi in realtà sono 8 byte.

Se si modifica il secondo FieldOffset su 8 o si cambia X in uint, questo scomparirà.

+0

@Reed - Grazie, ho cambiato subito a un ushort e Ricevo ancora l'errore, è ushort 4 byte? Ho cercato su msdn e sizeof (ushort) è 2, ma ottengo l'errore. Quando cambio il fieldoffset a 4, funziona. – SwDevMan81

+0

Ora la mia ipotesi è un problema di allineamento, devo avviare l'array su un limite di 4 byte? Non riesco a trovare nulla online – SwDevMan81

+1

Le matrici devono essere DWORD allineate nella CF. Vedi la mia risposta per maggiori dettagli e soluzioni alternative. – ctacke