Un amico mi ha chiesto come caricare in una struttura C# dei dati esportati da un software scritto in C per microcontrollore.
Se anche il microcontrollore parlasse 'managed' gli avrei suggerito di serializzare la struttura ma in questo caso tale soluzione non e' applicabile, ho quindi scritto questa funzioncina che prende i dati dal file binario e li rimappa nella struttura C#. Nulla di ecclatante ma dimostra l'uso di Marshal.PtrToStructure() e Marshal.StructureToPtr() che possono sempre venire utili.
[StructLayout(LayoutKind.Sequential)] public struct MyStruct
{
public Int32 a;
public string b;
}
public
MyStruct GetStruct(string file)
{
byte[] indata;
Int32 size;
using (FileStream fs=new FileStream(file,FileMode.Open))
{
using (BinaryReader sr=new BinaryReader(fs))
{
size=(Int32)sr.BaseStream.Length;
indata=new byte[size];
sr.Read(indata,0,size);
sr.Close();
}
fs.Close();
}
IntPtr pnt=Marshal.AllocHGlobal(size);
GCHandle pin=GCHandle.Alloc(pnt,GCHandleType.Pinned);
Marshal.Copy(indata,0,pnt,size);
MyStruct st2=(MyStruct) Marshal.PtrToStructure(pnt,typeof(MyStruct));
pin.Free();
Marshal.FreeHGlobal(pnt);
return st2;
}
Per esportare da C# a file:
Int32 size=Marshal.SizeOf(st);
IntPtr pnt=Marshal.AllocHGlobal(size);
GCHandle pin=GCHandle.Alloc(pnt);
Marshal.StructureToPtr(st,pnt,false);
byte[] data=new byte[size];
Marshal.Copy(pnt,data,0,data.Length);
pin.Free();
Marshal.FreeHGlobal(pnt);
using(FileStream fs=new FileStream(@"C:\data.bin",FileMode.Create))
{
using(BinaryWriter sw=new BinaryWriter(fs))
{
sw.Write(data,0,size);
sw.Flush();
sw.Close();
}
fs.Close();
}
Il grosso limite di GetStruct() e' ovviamente il fatto che e' legata a MyStruct, col framework 2.0 sara' possibile scrivere:
public <T> GetStruct(string file)
e usare
MyStruct ms=GetStuct<MyStruct>(@"c:\data.bin");
Power of Generics!
PS: Il tutto e' applicabile anche a VB.NET
Public Function GetStruct(Of T)(ByVal file as string) as T
Dim ms as MyStruct=GetStruct(of MyStruct)("c:\data.bin")