64位P / Invoke Idiosyncrasy

时间:2010-10-11 04:26:48

标签: c# .net 64-bit pinvoke

我正在尝试为P / Invoke正确地制作一些结构,但是在64位操作系统上进行测试时会发现奇怪的行为。

我有一个结构定义为:

/// <summary>http://msdn.microsoft.com/en-us/library/aa366870(v=VS.85).aspx</summary>
[StructLayout(LayoutKind.Sequential)]
private struct MIB_IPNETTABLE
{
    [MarshalAs(UnmanagedType.U4)]
    public UInt32 dwNumEntries;
    public IntPtr table; //MIB_IPNETROW[]
}

现在,要获取表的地址,我想像这样进行Marshal.OffsetOf()调用:

IntPtr offset = Marshal.OffsetOf(typeof(MIB_IPNETTABLE), "table");

这应该是4 - 我已经转储了缓冲区的字节以确认这一点以及用我的指针算法中的硬编码4替换上面的调用,这产生了正确的结果。

如果我实例化MIB_IPNETTABLE并执行以下调用,我确实得到了预期的4:

IntPtr offset = (IntPtr)Marshal.SizeOf(ipNetTable.dwNumEntries);

现在,在顺序结构中,字段的偏移量应该是前面字段大小的总和,对吗?或者是这种情况,当它是一个非托管结构时,偏移真的是8(在x64系统上),但只有在编组魔法之后变成4?有没有办法让OffsetOf()调用给我正确的偏移量?我可以使用对SizeOf()的调用,但对于较大的结构,OffsetOf()更简单。

1 个答案:

答案 0 :(得分:2)

在64位C / C ++构建中,由于对齐要求,table字段的偏移量将为8(除非您强制使用它)。我怀疑CLR对你做了同样的事情:

  

对象的成员按照它们出现时的顺序依次排列   导出到非托管内存。成员根据StructLayoutAttribute.Pack中指定的包装进行布局,并且可以是不连续的。

如果您需要该级别的控制权,您可能会使用该属性或使用LayoutKind.Explicit属性以及每个字段的FieldOffset属性。