C#P /调用结构对齐

时间:2009-08-11 08:04:55

标签: c# pinvoke alignment

我正试图在AMD64上从C#调用 NtGetContextThread 。问题是AMD64的 CONTEXT 结构需要在16字节边界上对齐,当我调用 NtGetContextThread 时,我总是得到STATUS_DATATYPE_MISALIGNMENT。我知道C#可以使用 Pack 属性对齐结构的各个成员,但它似乎无法对齐整个结构。我有什么方法可以做到这一点吗?

编辑:为了说清楚,我不想让个别成员对齐。我想对齐整个结构。

2 个答案:

答案 0 :(得分:2)

从您的问题来看,您是否完全理解StructLayout属性的Pack属性尚不清楚。有关详细信息,请参阅此msdn article

如果我理解正确,那么您正在寻找的是能够单独显式地对齐结构的每个成员。如果这是您的目标,您可以使用StructLayout和FieldOffset属性执行此操作,如下所示:

[StructLayout(LayoutKind.Explicit)]
public struct Message
{
    [FieldOffset(0)]
    public int a;
    [FieldOffset(4)]
    public short b;
    [FieldOffset(6)]
    public int c;
    [FieldOffset(22)] //Leave some empty space just for the heck of it.
    public DateTime dt;

}

请注意,.NET CF Marshaler有一些您可能不会期望的规则。例如,数组必须始终以4字节边界对齐。这个问题有workarounds,但你应该知道这样的问题可能会出现。

答案 1 :(得分:0)

我发现这样做的唯一方法是过度分配指针并变得不安全。

像这样:

[StructLayout(LayoutKind.Explicit)]
struct Foo
{
  /* fields go here */
}

var ptrMemory = Marshal.AllocHGlobal(sizeof(Foo)  + 64);
IntPtr ptrAligned = new IntPtr(64 * (((long)ptrMemory + 63) / 64));
MyStructPointer* Foo = (Foo*)ptrAligned;