Hallo,
das o.g. Snippet ist von mir, sollte das sein was du suchst, allerdings ist die Version nicht mehr ganz aktuell, hier die aktuelle Version:
/// <summary>
/// Kopiert Daten aus einem Byte-Array in eine entsprechende Strukture (struct). Die Struktur muss ein sequenzeilles Layout besitzen. ( [StructLayout(LayoutKind.Sequential)]
/// </summary>
/// <param name="array">Das Byte-Array das die daten enthält</param>
/// <param name="offset">Offset ab dem die Daten in die Struktur kopiert werden sollen.</param>
/// <param name="structType">System.Type der Struktur</param>
/// <returns></returns>
static object ByteArrayToStruct(byte[] array, int offset, Type structType)
{
if (structType.StructLayoutAttribute.Value != LayoutKind.Sequential)
throw new ArgumentException("structType ist keine Struktur oder nicht Sequentiell.");
int size = Marshal.SizeOf(structType);
byte[] tmp = new byte[size];
if (offset > 0)
Array.Copy(array, offset, tmp, 0, size);
else
tmp = array;
GCHandle structHandle = GCHandle.Alloc(tmp, GCHandleType.Pinned);
object structure = Marshal.PtrToStructure(structHandle.AddrOfPinnedObject(), structType);
structHandle.Free();
return structure;
}
Verwendung:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct MyStruct
{
int foo1;
int foo2;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
String str;
}
byte[] array = // ...
MyStruct structure = (MyStruct)ByteArrayToStruct(array, 0, typeof(MyStruct));
Das Prüfen der korrekten Arraylgröße ist raus geflogenen weil u.U. das Array kleiner sein kann als die dazugehörige Struktur! Dafür wird das u.U. unnötige Kopieren des Arrays vermieden.
Zu der Arraygröße:
Folgende Struktur hat die Größe 10:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct MyStruct
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
String str;
}
Klar, 10 ANSI Zeichen sind 10 Bytes groß.
Aber diese Struktur ist 16(!) Bytes groß:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct MyStruct
{
int foo;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
String str;
}
Int (32 bit) 4 Bytes + 10 Bytes = 16?
Das liegt am am Byte-Alignment, d.h. diese Struktur wird in 4Byte-Blöcke eingeteilt, die Größe ist ein Vielfaches von 4, es sind also "Lücken" in der Struktur
Das Array das in diese Struktur gemarshalt wird muss dennoch die Daten lückenlos enthalten, Marshal.PtrToStructure kopiert die Daten unter Berücksichtigung des Byte-Alignments.
Also Achtung bei solchen Aktionen, u.U. fehlen einfach Daten nachher in der Struktur.