Click here to Skip to main content
15,913,303 members
Articles / Programming Languages / C#

Convert a byte array to a struct which contains managed data

Rate me:
Please Sign up or sign in to vote.
1.76/5 (6 votes)
4 Jul 2007CPOL 64.3K   436   9   5
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:

C#
[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:

C#
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:

C#
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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generaldynamic byte array in structure Pin
jude_aj26-May-11 4:10
jude_aj26-May-11 4:10 
GeneralRe: dynamic byte array in structure Pin
LatencyXXX6-Aug-11 20:27
LatencyXXX6-Aug-11 20:27 
No, there is not unless you are doing something like the old TValBStr where you have a 1 byte field (e.g. UInt16 short) that represents the length of your string/byte array. From that, your structure would still remain constant and your struct size must be then calculated at runtime and known by the time the assignment hits the routine posted below.

You might be able to do something like this for generic types.

C#
public static T ByteArrayToStructure<T>(byte[] bytes) where T : struct {
  try {
    IntPtr ptr = Marshal.AllocHGlobal(bytes.Length);
    Marshal.Copy(bytes, 0, ptr, bytes.Length);
    T obj = (T)Marshal.PtrToStructure(ptr, typeof(T));
    Marshal.FreeHGlobal(ptr);
    return obj;
  } catch (Exception ex) {
    throw ex;
  }
}



But again.. the size is still needed to be known where bytes.Length => whatever your size is.
-Latency

Generalvery helpful ! but one question... Pin
koliv29-Jul-07 21:41
koliv29-Jul-07 21:41 
GeneralRe: very helpful ! but one question... Pin
vinh2b29-Jul-07 22:07
vinh2b29-Jul-07 22:07 
GeneralRe: very helpful ! but one question... Pin
koliv29-Jul-07 23:30
koliv29-Jul-07 23:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.