Ho un sistema in cui un agente remoto invia strutture serializzate (da un sistema C incorporato) da leggere e archiviare tramite IP/UDP. In alcuni casi ho bisogno di inviare gli stessi tipi di struttura. Ho pensato di avere un buon setup usando Marshal.PtrToStructure (receive) e Marshal.StructureToPtr (send). Tuttavia, un piccolo trucchetto è che gli interi bigian della rete devono essere convertiti nel mio formato little endian x86 da utilizzare localmente. Quando li rimando, big endian è la strada da percorrere.Marshal.PtrToStructure (e viceversa) e soluzione generica per lo scambio di endianness
Qui ci sono le funzioni in questione:
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;
}
e una struttura esempio veloce che potrebbe essere utilizzato in questo modo:
byte[] data = this.sock.Receive(ref this.ipep);
Request request = BytesToStruct<Request>(ref data);
Qualora la struttura in questione si presenta come:
[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;
}
Quale modo (generico) è possibile scambiare l'endianness durante il marshalling delle strutture? Il mio bisogno è tale che la "richiesta.sequenza" memorizzata localmente in questo esempio dovrebbe essere little-endian per la visualizzazione all'utente. Non voglio dover scambiare l'endianness in un modo specifico della struttura poiché si tratta di un problema generico.
Il mio primo pensiero è stato usare Reflection, ma non ho molta familiarità con quella funzione. Inoltre, speravo che là fuori ci sarebbe stata una soluzione migliore a cui qualcuno potesse puntare. Grazie in anticipo :)
Come ci sono voluti due anni perché qualcuno facesse notare che stiamo chiedendo la stessa qeuestion (http: // StackOverflow.com/domande/2480116/smistamento-a-big-endian byte-raccolta-in-a-struct-in-order-to-pull-out-Value) !? :-) – Pat