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")