This is not how you would declare it in C. If the entry in the file contains a string, you would declare a structure similar to:
struct Example { int mumble;
The corresponding C # declaration would look like this:
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] private struct Example { public int mumble; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)] public string text;
Usually you should use BinaryReader to read data. But it cannot handle strings like this directly, you have to read them as byte [] and convert the string yourself. You also cannot use declarative syntax, you need to write a call for each individual member of the structure.
A workaround for this, the marshal class already knows how to convert unmanaged structures to managed ones using the PtrToStructure () method. Here's a general implementation, it works for any type of blittable. Two versions, static, which are read from byte [], and an instance method that has been optimized to be read from the stream again. You would use FileStream or MemoryStream with this.
using System; using System.IO; using System.Runtime.InteropServices; class StructTranslator { public static bool Read<T>(byte[] buffer, int index, ref T retval) { if (index == buffer.Length) return false; int size = Marshal.SizeOf(typeof(T)); if (index + size > buffer.Length) throw new IndexOutOfRangeException(); var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); try { IntPtr addr = (IntPtr)((long)handle.AddrOfPinnedObject() + index); retval = (T)Marshal.PtrToStructure(addr, typeof(T)); } finally { handle.Free(); } return true; } public bool Read<T>(Stream stream, ref T retval) { int size = Marshal.SizeOf(typeof(T)); if (buffer == null || size > buffer.Length) buffer = new byte[size]; int len = stream.Read(buffer, 0, size); if (len == 0) return false; if (len != size) throw new EndOfStreamException(); var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); try { retval = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); } finally { handle.Free(); } return true; } private byte[] buffer; }
Unconfirmed, hope this works.
Hans passant
source share