Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6325787
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T16:57:37+00:00 2026-05-24T16:57:37+00:00

Based on suggestions from svick, I believe I can substancially simplify my post and

  • 0

Based on suggestions from svick, I believe I can substancially simplify my post and question. Below, is some complete code that demonstrates my problem and question, namely marshalling bytes to structures does not work the way I’d expect…
In the case of an object with two arrays seperated by another primitive, my object is not being marshalled to bytes the way I’d expect. Although I specify “Sequential”, the two byte[] arrays are put in the byte array first, with the uint following. What is going on?
In “real life” I am dealing with a binary file from someone else, where the data really is in the order byte[5] firstArray, uint firmwareVersion, byte[9] secondArray.

As requested, I have put a complete code example with comments.

namespace MarshallingExample
{
class Program
{
    static void Main(string[] args)
    {

        // first show that our Marshalling to/from objects to bytes is working ...
        Simple simpleObject = new Simple();
        simpleObject.HeaderInfo = new byte[5] { 1, 2, 3, 4, 5 };
        simpleObject.FirmwareRevision = 1234;
        byte[] simpleObjectBytes = Tools.ConvertObjectToBytes(simpleObject);
        Simple simpleObject2 = Tools.ConvertBytesToObject(simpleObjectBytes, 0, typeof(Simple)) as Simple;

        Complex complexObject = new Complex();
        complexObject.HeaderInfo = new byte[5] { 1, 2, 3, 4, 5 };
        complexObject.FirmwareRevision = 1234;

        complexObject.SoftwarePartNumber = new byte[9] { 11, 12, 13, 14, 15, 16, 17, 18, 19 };
        byte[] complexObjectBytes = Tools.ConvertObjectToBytes(complexObject);   // look at complexObjectBytes!!!
        // Notice that the two arrays come first in complexObjectBytes.  Not a problem here.
        Complex complexObject2 = Tools.ConvertBytesToObject(complexObjectBytes, 0, typeof(Complex)) as Complex;



        // Set up some data in MemoryStream(would really be in files) as it's actually given to us....
        MemoryStream memStreamSimple;
        memStreamSimple = new MemoryStream(9);
        memStreamSimple.Write(simpleObject.HeaderInfo, 0, 5);
        memStreamSimple.Write(BitConverter.GetBytes(simpleObject.FirmwareRevision), 0, 4);

        MemoryStream memStreamComplex;
        memStreamComplex = new MemoryStream(18);
        memStreamComplex.Write(complexObject.HeaderInfo, 0, 5);
        memStreamComplex.Write(BitConverter.GetBytes(complexObject.FirmwareRevision), 0, 4);
        memStreamComplex.Write(complexObject.SoftwarePartNumber, 0, 9);


        // now read and try to put in our structures....

        memStreamSimple.Seek(0, SeekOrigin.Begin);
        simpleObjectBytes = new byte[9];
        int count = memStreamSimple.Read(simpleObjectBytes, 0, 9);
        simpleObject2 = Tools.ConvertBytesToObject(simpleObjectBytes, 0, typeof(Simple)) as Simple;

        memStreamComplex.Seek(0, SeekOrigin.Begin);
        complexObjectBytes = new byte[18];
        count = memStreamComplex.Read(complexObjectBytes, 0, 18);
        // Note that following object is all messed up, probably because it was expecting the two arrays first.
        complexObject2 = Tools.ConvertBytesToObject(complexObjectBytes, 0, typeof(Complex)) as Complex;
    }
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class Simple
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
    private byte[] _headerInfo = new byte[5];
    public byte[] HeaderInfo
    {
        get
        {
            return _headerInfo;
        }
        set
        {
            _headerInfo = value;
        }
    }

    public uint FirmwareRevision
    {
        get;
        set;
    }


}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class Complex
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
    private byte[] _headerInfo = new byte[5];
    public byte[] HeaderInfo
    {
        get
        {
            return _headerInfo;
        }
        set
        {
            _headerInfo = value;
        }
    }

    public uint FirmwareRevision
    {
        get;
        set;
    }

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
    private byte[] _softwarePartNumber = new byte[9];
    public byte[] SoftwarePartNumber
    {
        get
        {
            return _softwarePartNumber;
        }
        set
        {
            _softwarePartNumber = value;
        }
    }

}

public static class Tools
{

    /// <summary>
    /// Convert an array of bytes starting at the offset provided into the specified type (struct or class).
    /// </summary>
    /// <param name="bytes"></param>
    /// <param name="startOffset"></param>
    /// <param name="type"></param>
    /// <returns>Newly created object of the specified type created from bytes given. NULL on any error.</returns>
    public static object ConvertBytesToObject(byte[] bytes, int startOffset, Type type)
    {
        object obj = null;
        int size = Marshal.SizeOf(type);

        if (size > 0)
        {
            if (size <= bytes.Length - startOffset)
            {
                IntPtr ptr = IntPtr.Zero;

                try
                {
                    ptr = Marshal.AllocHGlobal(size);
                    Marshal.Copy(bytes, startOffset, ptr, size);
                    obj = Marshal.PtrToStructure(ptr, type);
                }
                finally
                {
                    if (ptr != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(ptr);
                    }
                }
            }
            else
            {
                throw new Exception("ConvertBytesToObject: Requested offset + size of object exceeds length of bytes buffer to read.");
            }
        }
        else
        {
            throw new Exception("ConvertBytesToObject: Marshal.SizeOf(T) returned a size of 0.");
        }

        return obj;
    }

    /// <summary>
    /// Convert an object (struct or class) to an array of bytes.
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static byte[] ConvertObjectToBytes(object obj)
    {
        byte[] bytes = null;

        if (obj != null)
        {
            IntPtr ptr = IntPtr.Zero;
            Type type = obj.GetType();
            int size = Marshal.SizeOf(type);
            //int size = Marshal.SizeOf(obj.GetType());

            if (size > 0)
            {
                try
                {
                    ptr = Marshal.AllocHGlobal(size);
                    if (ptr != IntPtr.Zero)
                    {
                        Marshal.StructureToPtr(obj, ptr, false);
                        bytes = new byte[size];
                        Marshal.Copy(ptr, bytes, 0, size);
                    }
                }
                finally
                {
                    if (ptr != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(ptr);
                    }
                }
            }
            else
            {
                throw new Exception("ConvertObjectToBytes: Marshal.SizeOf(T) returned a size of 0.");
            }
        }

        return bytes;
    }




}

}

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T16:57:39+00:00Added an answer on May 24, 2026 at 4:57 pm

    If you run ildasm.exe on assembly then the cause of the problem becomes clear:

    enter image description here

    Note the mysterious <FirmwareRevision>k__BackingField field that got added to the class. You can probably guess where it came from, it is the auto-generated backing field for the automatic property FirmwareRevision. The native code sees the fields, not the properties. Which puts them in the wrong order.

    The fix is simple, you need to declare the backing field explicitly and avoid letting the compiler generate it:

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public class Complex {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
        private byte[] _headerInfo = new byte[5];
        private uint firmwareRevision;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
        private byte[] _softwarePartNumber = new byte[9];
    
        public uint FirmwareRevision {
            get { return firmwareRevision; }
            set { firmwareRevision = value; }
        }
        //etc..
    }
    

    Watch out for Pack = 1, it isn’t often correct. It matters in this case since the first field is 5 bytes long. The natural alignment puts firmwareRevision at offset 8, you’ll get it at offset 5.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Based on code suggestions here at stackoverflow, I've tried to extract an image from
I have a C# winform app that is collecting some data from console-based commands.
Based on this question it appears that the default template for CheckStyle will allow
Based on the code I've found, it seems that the Visitor is required to
I'm searching a software (web-based, php/mysql) that allows users to (anonymously/with registering) write suggestions
Based on the response to this question: Why does C++ have header files and
Based on my previous question here my new concern is how do I unit
Based on this question I don't want to litter my ready stuff waiting for
I'm looking for a right-click upload application like RightLoad - an application that can
I have a flash based game that has a high score system implemented with

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.