Неправильно выровнено или перекрыто ошибкой необъектного поля

Я пытаюсь создать следующую структуру:

    [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, это исчезнет.

Другие вопросы по тегам