【问题标题】:64 Bit P/Invoke Idiosyncrasy64 位 P/Invoke 特性
【发布时间】:2010-10-11 12:34:00
【问题描述】:

我正在尝试为 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() 对于较大的结构更简单。

【问题讨论】:

  • 该结构翻译不正确。事实上table 在一个内联数组中。

标签: c# .net 64-bit pinvoke


【解决方案1】:

在 64 位 C/C++ 构建中,由于对齐要求,table 字段的偏移量将为 8(除非您以其他方式强制执行)。我怀疑 CLR 也在对你做同样的事情:

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

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

【讨论】:

  • 感谢您确认我对非托管对齐的怀疑。我正在寻找使用 FieldOffset 的显式布局。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-22
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-12
相关资源
最近更新 更多