Неправильно выровнено или перекрыто ошибкой необъектного поля
Я пытаюсь создать следующую структуру:
[StructLayout(LayoutKind.Explicit, Size=14)]
public struct Message
{
[FieldOffset(0)]
public ushort X;
[FieldOffset(2)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst=5)]
private ushort[] Y;
[FieldOffset(12)]
public ushort Z;
}
и я получаю следующую ошибку:
Не удалось загрузить тип "Сообщение" из сборки, поскольку он содержит поле объекта со смещением 4, которое неправильно выровнено или перекрыто полем, не являющимся объектом.
Кто-нибудь знает, почему это вызывает ошибку?
Примечание: я не могу использовать Pack, потому что я работаю с компактной структурой. Благодарю.
2 ответа
CF Marshaler не очень хорош в этом, и то, что вы пытаетесь, не поддерживается. Проблема в том, что он знает, что первый элемент не выровнен, но, похоже, не понимает, что каждый элемент в массиве также будет выровнен.
Вы можете увидеть, как работает поведение в этом примере:
[StructLayout(LayoutKind.Explicit, Size = 14)]
public struct Message
{
[FieldOffset(0)]
public ushort X;
[FieldOffset(2)]
private ushort Y1;
[MarshalAs(UnmanagedType.LPArray)]
[FieldOffset(4)]
private ushort[] Y2;
[FieldOffset(12)]
public ushort Z;
}
Для такого типа структуры я никогда не позволяю маршалеру пытаться обрабатывать каждый из членов в любом случае. Структура небольшая, поэтому разбивайте каждый отдельный элемент следующим образом:
[StructLayout(LayoutKind.Explicit, Size = 14)]
public struct Message
{
[FieldOffset(0)]
public ushort X;
[FieldOffset(2)]
private ushort Y1;
[FieldOffset(4)]
private ushort Y2;
[FieldOffset(6)]
private ushort Y3;
[FieldOffset(8)]
private ushort Y4;
[FieldOffset(10)]
private ushort Y5;
[FieldOffset(12)]
public ushort Z;
}
или используйте смоделированный "союз", как это:
public struct Y
{
public ushort a;
public ushort b;
public ushort c;
public ushort d;
public ushort e;
}
[StructLayout(LayoutKind.Explicit, Size = 14)]
public struct Message
{
[FieldOffset(0)]
public ushort X;
[FieldOffset(2)]
private Y Y;
[FieldOffset(12)]
public ushort Z;
}
Проблема возникает, потому что ваш массив перекрывается "X". ulong в C# - это UInt64 (в C++ ulong - это UInt32), поэтому на самом деле это 8 байтов.
Если вы измените свой второй FieldOffset на 8, или измените X на uint, это исчезнет.