64位P /调用Idiosyncrasy

问题描述:

我想正确地为一个P/Invoke组织一些结构,但在64位操作系统上测试时发现奇怪的行为。64位P /调用Idiosyncrasy

我有一个结构定义为:

/// <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代替了上述调用,从而产生了正确的结果。

我得到预期的4,如果我实例MIB_IPNETTABLE并执行以下电话:结构中的一个字段的偏移量应该是前场的大小之和,正确

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

现在,在一个连续的?或者当它是一个非托管结构的情况下,偏移量真的是8(在x64系统上),但是仅在编组魔法之后变为4?有没有办法让OffsetOf()调用给我正确的偏移量?我可以使用调用SizeOf(),但OffsetOf()更简单的更大的结构。

+0

该结构翻译不正确。事实上,在一个内联数组中的“表”。 – 2014-01-13 22:30:19

在64位C/C++版本中,由于对齐要求(除非您强制要求),您的table字段的偏移量将为8。我怀疑是CLR在做同样的给你:

对象的成员布局顺序,在它们出现时 出口到非托管内存的顺序。会员根据StructLayoutAttribute.Pack中规定的包装进行布置,并且可以不连续。

您可以wnat使用该属性或使用LayoutKind.Explicit属性与FieldOffset属性沿每个字段,如果你需要控制的那个级别。

+0

谢谢您确认我对非托管路线的怀疑。 FieldOffset的显式布局是我正在寻找的。 – 2010-10-11 14:59:52