如何为pinvoke保留一组内存类型

时间:2015-02-16 17:46:52

标签: c# struct pinvoke padding

我需要使用这个Kernel32结构:NUMA_NODE_RELATIONSHIP

但保留字段声明为:BYTE Reserved[20];

要正确地声明结构,有没有比声明更好的方法:

public struct NUMA_NODE_RELATIONSHIP
{
    public UInt16 NodeNumber;
    public BYTE Reserved1;
    public BYTE Reserved2;
    ...
    public BYTE Reserved20;
    public GROUP_AFFINITY GroupMask;
}

或使用:

[StructLayout(LayoutKind.Explicit)]
public struct NUMA_NODE_RELATIONSHIP2
{
    [FieldOffset(0)]
    public UInt16 NodeNumber;
    // [FieldOffset(2)] // **
    // public byte Reserved;
    [FieldOffset(22)] 
    public GROUP_AFFINITY GroupMask;
}

**我不确定我的代码是否正常......这里FieldOffset是OS字大小(32或64位)的字节偏移还是倍数? WIN32 API pad是否对齐struct字段,如果是,如何?如果两者都填充或两者都没有填充,我很好,否则我的代码会被窃听。这不是我的主要问题。那个插入只是提到我的代码不一定按照它编写的方式工作。我的主要问题是这一个:

声明带有数组的pinvoke结构的最佳方法是什么? 我想知道两者是否合适,哪一个是首选和/或是否有更好的方式来声明该结构,因为我使用了添加工件,这使得它很难写和/或更难理解。

2 个答案:

答案 0 :(得分:1)

WinAPI以大小的自然大小对齐大多数小类,因此WORD为16位,DWORD为32位。 BYTE是一个字节,不对齐。在需要的地方插入填充以实现下一个成员的正确对齐。

这里的诀窍是GROUP_AFFINITY的对象。我认为这是2个字节,因为它的所有成员都是WORD

我认为它的2字节对齐的第二个原因是因为微软倾向于命名它的填充(!)。如果在Reserved之后有2个字节的未命名填充,则Microsoft会改为BYTE reserved[22]

是的,.Net字段偏移量也以字节为单位。

答案 1 :(得分:1)

声明如下:

[StructLayout(LayoutKind.Sequential)]
public struct NUMA_NODE_RELATIONSHIP
{
    public uint NodeNumber;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
    public byte[] Reserved;
    public GROUP_AFFINITY GroupMask;
}

不需要明确的布局。让编组器使用与C ++编译器相同的规则布局结构更有意义。特别是当GROUP_AFFINITY具有4或8个字节的对齐时,具体取决于机器指针的大小。显然,上述内容依赖于您GROUP_AFFINITY正确。

相关问题