Convert a byte array to a struct which contains managed data
How to convert a managed type to a byte array and a byte array to a struct.
Introduction
We can't convert a bytes array to a structure which contains managed type. Instead of defining your structure the traditional way, you can use [MarshalAs(UnmanagedType.ByValArray, SizeConst = n)]
to define a managed type variable in order to convert a bytes array to a structure or convert a structure to a bytes array.
Using the code
In this sample, I have used only one class. I'm going to create an instance of the class, then convert the instance to a bytes array, and convert the bytes array to another instance of the class:
[StructLayout(LayoutKind.Sequential)]
public class LogFont
{
/// <summary>
/// 4 bytes
/// </summary>
int lfHeight;
/// <summary>
/// 4 bytes
/// </summary>
int lfWidth;
/// <summary>
/// 4 bytes
/// </summary>
int lfEscapement;
/// <summary>
/// 4 bytes
/// </summary>
int lfOrientation;
/// <summary>
/// 4 bytes
/// </summary>
int lfWeight;
/// <summary>
/// 1 byte
/// </summary>
byte lfItalic;
/// <summary>
/// 1 byte
/// </summary>
byte lfUnderline;
/// <summary>
/// 1 byte
/// </summary>
byte lfStrikeOut;
/// <summary>
/// 1 byte
/// </summary>
byte lfCharSet;
/// <summary>
/// 1 byte
/// </summary>
byte lfOutPrecision;
/// <summary>
/// 1 byte
/// </summary>
byte lfClipPrecision;
/// <summary>
/// 1 byte
/// </summary>
byte lfQuality;
/// <summary>
/// 1 byte
/// </summary>
byte lfPitchAndFamily;
/// <summary>
/// 64 bytes
/// </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
byte[] lfFaceName;
}
Converting Methods
Use the two methods shown below to convert objects:
public static LogFont GetLogFontFromBff(byte[] bff)
{
LogFont logFont = new LogFont();
IntPtr ptPoit = Marshal.AllocHGlobal(92);
Marshal.Copy(bff, 0, ptPoit, 92);
logFont = (LogFont)Marshal.PtrToStructure(ptPoit, typeof(LogFont));
Marshal.FreeHGlobal(ptPoit);
return logFont;
}
public static byte[] LogfontToByteArray(LogFont logFont)
{
IntPtr ptPoint = Marshal.AllocHGlobal(92);
Marshal.StructureToPtr(logFont, ptPoint, true);
byte[] bff = new byte[92];
Marshal.Copy(ptPoint, bff, 0, 92);
Marshal.FreeHGlobal(ptPoint);
return bff;
}
Note
Let's remember not to use:
byte[] buffer = new byte[92];
GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Marshal.StructureToPtr(logFont, h.AddrOfPinnedObject(), false);
h.Free();
return buffer;
because you'll have an exception from COM after calling the LogfontToByteArray
method too many times.