Have a look at the System.Runtime.InteropServices.Marshal class. It provides a lot of usefull functions for interoperability.
Marshalling blittable types (int, float etc) is easy. However, other types - like strings - require a bit more work.
For example, in your case you could marshal the struct like this:
// force "nice" memory layout, marshal strings as ANSI strings[StructLayout(LayoutKind.Sequential, Pack=4, CharSet = CharSet.Ansi)]struct MonsterStruct { // marshal as a constant size array (char[128]) [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] public string sName; public int ID; public int HP; public int Sight; public int Speed; // ... // writes this instance to disc public void Save(string fileName) { // first, get the unmanaged size of the structur int size = Marshal.SizeOf(typeof(MonsterStruct)); // allocate an unmanaged buffer of the right size IntPtr data = Marshal.AllocCoTaskMem(size); try { // marshal structure to unmanaged memory // this step will copy all blittable members // For the string-member, this will re-encode // the string to a ANSI string, truncate it to 127 // characters if necessary (buffer is 128 = 127 + zero byte) Marshal.StructureToPtr(this, data, false); // create managed buffer and copy marshalled data there byte[] buffer = new byte[size]; Marshal.Copy(data, buffer, 0, buffer.Length); // write buffer using the simple stream functions using(Stream s = File.Open(fileName, FileMode.Truncate, FileAccess.Write)) { s.Write(buffer, 0, buffer.Length); } } finally { Marshal.FreeCoTaskMem(data); } } public static MonsterStruct Load(string fileName) { // first, get the unmanaged size of the structur int size = Marshal.SizeOf(typeof(MonsterStruct)); // allocate a buffer that can hold the native image of the struct byte[] buffer = new byte[size]; // read data from file using(Stream s = File.OpenRead(fileName)) { s.Read(buffer, 0, size); } // allocate unmanaged memory IntPtr ptr = Marshal.AllocCoTaskMem(buffer.Length); try { // copy buffer to unmanaged memory Marshal.Copy(buffer, 0, ptr, buffer.Length); // marshal to MonsterStruct: object ms = Marshal.PtrToStructure(ptr, typeof(MonsterStruct)); return (MonsterStruct)ms; } finally { Marshal.FreeCoTaskMem(ptr); } }};class Program { static void Main() { // create a struct MonsterStruct ms = new MonsterStruct(); ms.sName = "This is a very simple test!"; ms.ID= 1234; ms.HP = 12; ms.Sight = 20; ms.Speed = 5; // save it ms.Save("c:\\struct.bin"); // load the same struct from disc again: MonsterStruct loadedMS = MonsterStruct.Load("c:\\struct.bin"); // show on console: Console.WriteLine(loadedMS.sName); Console.WriteLine(loadedMS.ID); Console.WriteLine(loadedMS.HP); Console.WriteLine(loadedMS.Sight); Console.WriteLine(loadedMS.Speed); Console.ReadLine(); }}
To make the code more efficient, you can use unsafe/fixed in this context:
public void Save(string fileName) { // first, get the unmanaged size of the structur int size = Marshal.SizeOf(typeof(MonsterStruct)); // allocate a memory buffer byte[] buffer = new byte[size]; unsafe { // pin the data array and get a pointer to the first element fixed(byte * ptrBuffer = &buffer[0]) { // marshal structure to memory Marshal.StructureToPtr(this, new IntPtr(ptrBuffer), false); } } // write buffer using the simple stream functions using(Stream s = File.Open(fileName, FileMode.Truncate, FileAccess.Write)) { s.Write(buffer, 0, buffer.Length); } } public static MonsterStruct Load(string fileName) { // first, get the unmanaged size of the structur int size = Marshal.SizeOf(typeof(MonsterStruct)); // allocate a buffer that can hold the whole file byte[] buffer = new byte[size]; // read data from file using(Stream s = File.OpenRead(fileName)) { s.Read(buffer, 0, size); } unsafe { // pin the data array and get a pointer to the first element fixed(byte * ptrBuffer = &buffer[0]) { // marshal the structure to the byte array object ms = Marshal.PtrToStructure(new IntPtr(ptrBuffer), typeof(MonsterStruct)); // all done :) return (MonsterStruct)ms; } } }
Hope that helps.
Oh, btw, on the native side, you can use this layout of the structure:
struct MonsterStruct { char sName[128]; int ID; int HP; int Sight; int Speed;};
Be sure to set the member alignment to 4 bytes though!
Regards,
Andre