How can I map byte[] data to struct data (preferably using managed code)

  • Thread starter Thread starter Marquee
  • Start date Start date
M

Marquee

Hello,

This is my first program c#, my background is c++. One thing I would
like to do is put binary data (e.g. a record from disk, or network
packet) in a struct. In C++ I would create the struct and memcpy() the
data into it thus creating a structured overlay. The struct can have
variable length e.g.

struct CRecord //Just for example
{
int m_iLength;
int m_iType;
string m_Whatever; //C++ would be like char m_Whatever[10];
byte[] m_AnyData; //Variable length field.
};

I thried this in c# with MemoryStream and BinaryFormatter, but these
methods put some .NET specific medata data into the stream. Is there a
managed way to do accomplish this?

C++ equivalent:

CRecord *NewRecord( unsigned char *pData, int cbData )
{
//Data validation here
CRecord *pRec = (CRecord*) new char( cbData );
memcpy( pRec, pData, cbData );
return( pRec);
}

Can somebody help to point out a direction/solution.
Thanx!
 
Hi,
you must create c# struct that map your c++ struct. Add attribute
[StructLayout(LayoutKind.Sequential)] to c# struct.
Next step is to use static methods of Marshal class to copy data from
unmanaged memory to managed memory (c# struct).
Below there is a snippet code that read from file data and copy its to a c#
struct.
Thanks to Corrado Cavalli for this snipped.
http://www.ugidotnet.org/PermaLink.aspx?guid=c4ddfbf2-03c3-4823-af31-ec2f2bf7d2cd

[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();
}
 
Back
Top