如何为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
是否正确。
我需要使用这个 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
是否正确。