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

How to reserve an array of memory type for pinvoke

我需要使用这个 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 是否对齐结构字段,如果是,如何对齐?如果两者都被填充或都没有被填充,我很好,否则我的代码有问题。那不是我的主要问题。该插入只是为了说明我的代码不一定像编写的那样工作。我的主要问题是这个:

声明其中包含数组的 pinvoke 结构的最佳方法是什么? 我想知道两者是否都可以,哪个是首选 and/or 如果有更好的方法来声明该结构,因为我使用的这两种方法都添加了使编写时间更长的工件 and/or 更难理解。

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

这里比较棘手的是 GROUP_AFFINITY 的对齐。我认为它是 2 个字节,因为它的所有成员都是 WORD.

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

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

这样声明:

[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 是否正确。