2009-07-27 9 views
8

Próbuję utworzyć następującą strukturę:nieprawidłowo wyrównane lub zakryte przez błędu pola zakaz obiektu

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

i pojawia się następujący błąd:

Nie można załadować typu „Wiadomość” z złożenie, ponieważ zawiera pole obiektu przy przesunięciu 4, które jest niepoprawnie wyrównane lub zachodzi na pole nieobiektowe.

Czy ktoś wie, dlaczego powoduje to błąd?

Uwaga: Nie można używać pakietu, ponieważ pracuję z kompaktową strukturą. Dzięki.

Odpowiedz

8

Marshaler CF nie jest tak dobry w tego typu sytuacjach, a to, co próbujesz, nie jest obsługiwane. Problem polega na tym, że wie, że pierwszy element nie jest wyrównany, ale wydaje się, że nie rozumie, że każdy element w tablicy również nie będzie wyrównany.

Możesz zobaczyć zachowanie działa w tym przykładzie:

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

Dla tego typu struktury, nigdy nie pozwól marshaler starają się obsłużyć każdego z członków tak. Struktura ta jest niewielka, więc wyrwać każdą poszczególną pozycję tak:

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

lub użyj symulowaną „Unia” tak:

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, więc najprostsza odpowiedź znajduje się w komentarzu poniżej: Tablice muszą być wyrównane do DWORD w CF – SwDevMan81

+0

@cena: Czy możesz skierować mnie do referencji, która zawiera szczegółowe informacje o CF Marshaler (np. Że tablice muszą być DWORD podzielone)? – Odrade

+0

@david: Nie znam jednego. Wszystko, co wiem o marszu i jego możliwościach (lub ich braku) pochodzi ze spotkań i rozmów z zespołem CF, w połączeniu z wieloletnim doświadczeniem próbującym zmusić go do zrobienia tego, co chcę. – ctacke

1

Problem występuje, ponieważ tablica pokrywa się z "X". ulong, w języku C#, to UInt64 (w C++, ulong to UInt32), czyli w rzeczywistości 8 bajtów.

Jeśli zmienisz drugi zestaw FieldOffset na 8 lub zmienisz X na uint, zniknie.

+0

@Reed - Dzięki, zmieniłem go teraz do ushort i Nadal dostaję błąd, to jest 4 bajty? Sprawdziłem na msdn i sizeof (ushort) jest 2, ale pojawia się błąd. Kiedy zmienię offset pola na 4, to działa. – SwDevMan81

+0

Zgaduję, że teraz jest to problem wyrównania, czy muszę uruchomić tablicę na granicy 4-bajtowej? Nie mogę znaleźć niczego online – SwDevMan81

+1

Tablice muszą być wyrównane do DWORD w CF. Zobacz moją odpowiedź, aby uzyskać więcej szczegółów i potencjalnych obejść. – ctacke

Powiązane problemy