salocinx
salocinx

Reputation: 3823

How to convert a C++ struct to C# equivalent?

This is my C++ struct (the docs say that each instance has to be exactly 10 bytes in size):

#pragma pack (1)
struct LaserPoint {
    WORD x;
    WORD y;
    byte colors[6];
};

I made the following C# struct:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct LaserPoint {
    public UInt16 x;                   // 2 bytes
    public UInt16 y;                   // 2 bytes
    public byte[] colors;              // 6 bytes
}

Here's my full test code in my C# project:

using System;
using System.Runtime.InteropServices;

namespace StructSizeTest {
    class Program {

        [StructLayout(LayoutKind.Sequential, Pack=1)]
        public struct LaserPoint {
            public UInt16 x;                   // 2 bytes
            public UInt16 y;                   // 2 bytes
            public byte[] colors;              // byte[6] = 6 bytes
        }

        static void Main(string[] args) {

            LaserPoint point = new LaserPoint();
            point.x = (UInt16)16384;
            point.y = (UInt16)32768;
            point.colors = new byte[6];
            point.colors[0] = 255;
            point.colors[1] = 255;
            point.colors[2] = 255;
            point.colors[3] = 255;
            point.colors[4] = 255;
            point.colors[5] = 255;

            Console.WriteLine("LaserPoint.Size: " + Marshal.SizeOf(point));

            Console.ReadLine();
        }

    }
}

This is the output on the console:

LaserPoint.Size: 8

Why is point 8 bytes in size and not 10 bytes?

UInt16  = 2 bytes
UInt16  = 2 bytes
byte[6] = 6 bytes
Total   = 10 bytes ?

What I am missing here?

Upvotes: 2

Views: 907

Answers (2)

adjan
adjan

Reputation: 13652

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct LaserPoint {
    public UInt16 x;                   // 2 bytes
    public UInt16 y;                   // 2 bytes
    public byte[] colors;              // 6 bytes
}

byte[] colors is not 6 bytes wide. It is not even an actual array, but a reference to a byte array on the heap. Depending on your platform, it has either 32 bit (4 bytes) or 64 bit (8 bytes) in size (internally, it is a pointer). That is why you are getting a size of 8 bytes as a result (2 byte + 2 byte + 4 byte). On a 64 bit platform you would get a size of 12 bytes (2+2+8).

To have the struct behave like a C++ struct add the MarshalAsAttribute and specify UnmanagedType.ByValArray and SizeConst:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct LaserPoint {
    public UInt16 x;                  
    public UInt16 y;                         
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
    public byte[] colors;             
}

Upvotes: 5

Elvis Dukaj
Elvis Dukaj

Reputation: 7368

I think the problem is with the array... Try this:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct LaserPoint {
    public UInt16 x;                   // 2 bytes
    public UInt16 y;                   // 2 bytes
    [MarhalAs(UnmanagedType.ByValArray, SizeConst = 6]
    public byte[] colors;              // 6 bytes
}

Upvotes: 2

Related Questions