2016-07-20 7 views
0

Ich versuche, Union-ähnliche Struktur mit Byte [] Feld zu erstellen. Also das nächste Typdeklaration verursacht einen Fehler in Laufzeit:Marshalling Array-Feld in union-like Struktur

[StructLayout(LayoutKind.Explicit)] 
public struct Int64ByteArr 
{ 
    [FieldOffset(0)] 
    public UInt64 u64; 
    [FieldOffset(0)] 
    public Int64 s64; 
    [FieldOffset(0), MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]   
    public byte[] bytes; 
} 

wenn eine Funktion aufrufen, die Variable dieses Typs verwendet, Programm verursacht Ausnahme mit dieser Beschreibung:

Необработанное исключение типа „System.TypeLoadException“ в System.Windows.Forms.dll Дополнительные сведения: Не удалось загрузить тип "Int64ByteArr" из сборки "ChalengeCalc, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null", так как он содержит поле объекта со смещением 0, которое н еверно выровнено или перекрыто полем, не представляющим объект.

Übersetzung Englisch: nicht behandelte Ausnahme des Typs "System.TypeLoadException" in System.Windows.Forms.dll) Zusätzliche Informationen: Fehler Typ "Int64ByteArr" von „ChalengeCalc, Version = 1.0.0.0, Culture = neutral laden PublicKeyToken = null“Assembly weil es Feld Objekt mit oaffset enthält 0, was falsch von überschwemmt durch Feld ausgerichtet ist, die ein Objekt nicht präsentiert

ich versuche auch diese Variante:

[StructLayout(LayoutKind.Sequential)] 
public struct ByteArr8 
{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 
    public byte[] bytes; 
    public Byte this[int idx] 
    { 
     get 
     { 
      if (idx < 0 || idx > 7) return 0; 
      return bytes[idx]; 
     } 
     set 
     { 
      if (idx < 0 || idx > 7) return; 
      bytes[idx] = value; 
     } 
    } 
} 
[StructLayout(LayoutKind.Explicit)] 
public struct Int64ByteArr 
{ 
    [FieldOffset(0)] 
    public UInt64 u64; 
    [FieldOffset(0)] 
    public Int64 s64; 
    [FieldOffset(0)] 
    public ByteArr8 bytes; 
} 

es hängt mit der gleichen Ausnahme. Also gibt es eine Frage: "Wie?"

+0

Mögliches Duplikat von [C# pinvoke Strukturen mit Union und Arrays] (http://stackoverflow.com/questions/20274284/c-sharp-pinvoke-structs-with-union-and-arrays) –

+2

Sie können eine Referenz nicht überlappen zu einem Referenztyp wie Byte [] mit einem Werttyp Wert. Das vermasselt den Müllsammler. Sie müssen stattdessen einen Puffer fester Größe verwenden. Da das Array die gleiche Größe wie das Int64 hat, ist eine andere sehr einfache Problemumgehung, BitConverter.GetBytes() zu verwenden, um die Bytewerte zu lesen. –

Antwort

1

In Ihrem speziellen Fall können Sie die Byte-Array Feldmarschalls nur und Getter/Setter für die andere bieten:

[StructLayout(LayoutKind.Sequential)] 
struct Int64ByteArr 
{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 
    public byte[] bytes; 
    public UInt64 u64 
    { 
     get { return BitConverter.ToUInt64(bytes, 0); } 
     set { bytes = BitConverter.GetBytes(value); } 
    } 
    public Int64 s64 
    { 
     get { return BitConverter.ToInt64(bytes, 0); } 
     set { bytes = BitConverter.GetBytes(value); } 
    } 
} 

Hinweis: inspiriert von David Heffernan Kommentar zu this question.

Im Allgemeinen müssten Sie benutzerdefinierte Marshalling verwenden, glaube ich.