19

我正在尝试创建以下结构:

    [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,因为我正在使用紧凑的框架。谢谢。

4

2 回答 2

14

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;
}

对于这种类型的结构,无论如何我从不让 marshaler 尝试处理每个成员。结构很小,所以像这样分解每个单独的项目:

[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;
}
于 2009-07-27T20:24:40.860 回答
4

出现问题是因为您的数组与“X”重叠。ulong 在 C# 中是 UInt64(在 C++ 中,ulong 是 UInt32),所以它实际上是 8 个字节。

如果您将第二个 FieldOffset 更改为 8,或将 X 更改为 uint,这将消失。

于 2009-07-27T19:24:56.797 回答