Это моя структура C++ (в документации указано, что размер каждого экземпляра должен быть ровно 10 байт):
#pragma pack (1)
struct LaserPoint {
WORD x;
WORD y;
byte colors[6];
};
Я сделал следующую структуру C#:
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct LaserPoint {
public UInt16 x; // 2 bytes
public UInt16 y; // 2 bytes
public byte[] colors; // 6 bytes
}
Вот мой полный тестовый код в моем проекте C#:
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();
}
}
}
Это вывод на консоли:
LaserPoint.Size: 8
Почему point
имеет размер 8 байтов, а не 10?
UInt16 = 2 bytes
UInt16 = 2 bytes
byte[6] = 6 bytes
Total = 10 bytes ?
Что мне здесь не хватает?
Думаю, проблема в массиве ... Попробуйте следующее:
[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
}
Большое спасибо! Я решил принять ответ Адриана как решение, поскольку он добавил полезное объяснение. Но я тоже поддержал вашу.
[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
не имеет ширины 6 байт. Это даже не фактический массив, а ссылка на массив байтов в куче. В зависимости от вашей платформы, он имеет размер 32 бита (4 байта) или 64 бита (8 байтов) (внутренне это указатель). Вот почему в результате вы получаете размер 8 байт (2 байта + 2 байта + 4 байта). На 64-битной платформе вы получите размер 12 байт (2 + 2 + 8).
Чтобы struct
вел себя как C++ struct
, добавьте MarshalAsAttribute
и укажите UnmanagedType.ByValArray
и SizeConst
:
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct LaserPoint {
public UInt16 x;
public UInt16 y;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public byte[] colors;
}
Поскольку массив не является массивом фиксированного размера времени компиляции. Думайте об этом больше как о указателе в C++.