如何正确编组c#中的非托管数组而不安全

时间:2016-05-06 08:46:37

标签: c# marshalling

我有非托管结构:

typedef struct 
 {
    char  a[48];
    BYTE  b;
    BYTE  c;
    BYTE  d;            
    BYTE  e;            
    BYTE  f;
    BYTE  x;
    char  y[32];
    char  z[128][32];
  }SOMELIKE_STRUCT

我尝试编组它,因为它是在StackOverflow中的另一个线程中编写的:

    [StructLayout(LayoutKind.Explicit, Pack = 1)]
    public struct SOMELIKE_STRUCT
    {
        [FieldOffset(0)]
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 48)]
        public byte[] a;
        [FieldOffset(48)]
        public byte b;
        [FieldOffset(49)]
        public byte c;
        [FieldOffset(50)]
        public byte d;
        [FieldOffset(51)]
        public byte e;
        [FieldOffset(52)]
        public byte f;
        [FieldOffset(53)]
        public byte x;
        [FieldOffset(54)]
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType=UnmanagedType.U1, SizeConst = 32)]
        public byte[] y;
        [FieldOffset(86)]
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType=UnmanagedType.Struct, SizeConst = 128)]
        public STRUCT[] z;
    }

[StructLayout(LayoutKind.Explicit, Pack = 1)]
    public struct STRUCT
    {
        [FieldOffset(0)]
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 32)]
        public byte[] name;
    }

我有例外:

System.TypeLoadException未处理   附加信息:无法从程序集中加载“SOMELIKE_STRUCT”类型      'ConsoleApplication2,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'因为      它包含偏移'54'处的对象字段,该字段未正确对齐或重叠      通过非对象字段。

  1. 当我使用new创建此结构时会出现异常:

    SOMELIKE_STRUCT l =新SOMELIKE_STRUCT();

  2. 异常显示我何时使用该结构创建类(当进入构造函数时)(在创建该结构的实例之前)

2 个答案:

答案 0 :(得分:3)

由于你的定义似乎是正确的,所以无法弄清楚这里发生了什么。

将布局更改为顺序并删除手动字段偏移似乎有效:

[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct SOMELIKE_STRUCT
{
    [MarshalAs( UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 48 )]
    public byte[] a;
    public byte b;
    public byte c;
    public byte d;
    public byte e;
    public byte f;
    public byte x;
    [MarshalAs( UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 32 )]
    public byte[] y;
    [MarshalAs( UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 128 )]
    public STRUCT[] z;
}

[StructLayout( LayoutKind.Sequential, Pack = 1 )]
public struct STRUCT
{
    [MarshalAs( UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 32 )]
    public byte[] name;
}

使用Marshal.SizeOf检查大小可得到4182个字节,使用Marshal.OffsetOf检查生成的布局会产生与原始代码相同的偏移量。我相信这里的其他人可以详细说明为什么会这样。

答案 1 :(得分:1)

struct 中包含的结构和表必须放在word的倍数地址(x86 / x64为4/8字节)。