Ich habe ein System, wo ein Remote-Agent serialisierte Strukturen (von einem eingebetteten C-System) für mich über IP/UDP lesen und speichern sendet. In einigen Fällen muss ich die gleichen Strukturtypen zurücksenden. Ich dachte, ich hätte ein gutes Setup mit Marshal.PtrToStructure (receive) und Marshal.StructureToPtr (send). Ein kleiner Fehler ist jedoch, dass die Netzwerk-Big-Endian-Integer in mein x86-Little-Endian-Format konvertiert werden müssen, um lokal verwendet zu werden. Wenn ich sie wieder sende, ist Big Endian der richtige Weg.Marshal.PtrToStructure (und wieder zurück) und generische Lösung für Endianness Swapping
Hier sind die Funktionen in Frage:
private static T BytesToStruct<T>(ref byte[] rawData) where T: struct
{
T result = default(T);
GCHandle handle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
try
{
IntPtr rawDataPtr = handle.AddrOfPinnedObject();
result = (T)Marshal.PtrToStructure(rawDataPtr, typeof(T));
}
finally
{
handle.Free();
}
return result;
}
private static byte[] StructToBytes<T>(T data) where T: struct
{
byte[] rawData = new byte[Marshal.SizeOf(data)];
GCHandle handle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
try
{
IntPtr rawDataPtr = handle.AddrOfPinnedObject();
Marshal.StructureToPtr(data, rawDataPtr, false);
}
finally
{
handle.Free();
}
return rawData;
}
Und ein kurzes Beispiel Struktur, die wie folgt verwendet werden könnten:
byte[] data = this.sock.Receive(ref this.ipep);
Request request = BytesToStruct<Request>(ref data);
Ändert sich die Struktur in Frage wie folgt aussieht:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
private struct Request
{
public byte type;
public short sequence;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public byte[] address;
}
Was (generische) Weise kann ich die Endianness tauschen, wenn Sie die Strukturen marshallen? Mein Bedarf ist derart, dass die lokal gespeicherte "request.sequence" in diesem Beispiel Little-Endian sein sollte, um dem Benutzer angezeigt zu werden. Ich möchte die Endianz nicht strukturspezifisch austauschen müssen, da es sich um ein generisches Problem handelt.
Mein erster Gedanke war Reflection zu verwenden, aber ich kenne diese Funktion nicht sehr gut. Außerdem hoffte ich, dass es da draußen eine bessere Lösung geben würde, auf die mich jemand hinweisen könnte. Vielen Dank im Voraus :)
Wie hat es zwei Jahre gedauert, bis jemand darauf hingewiesen hat, dass wir die gleiche Frage stellen (http: // stackoverflow.com/questions/2480116/Marshalling-a-Big-Endian-Byte-Sammlung-in-Struktur-in-Order-to-Pull-out-Wert)!? :-) – Pat