【问题标题】:C# P/invoke structure alignmentC# P/invoke 结构对齐
【发布时间】:2010-11-18 13:00:42
【问题描述】:

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

编辑:为了清楚起见,我不想对齐单个成员。我想对齐整个结构。

【问题讨论】:

    标签: c# pinvoke alignment


    【解决方案1】:

    从您的问题来看,尚不清楚您是否完全理解 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,但你应该知道这样的问题可能会突然出现。

    【讨论】:

    • 不,这不是我想要做的。我想在 16 字节边界上对齐 整个 CONTEXT 结构,而不是像 DECLSPEC_ALIGN 这样的单个字段。我知道 Pack 属性的作用,非常感谢。目前我正在使用 16 字节对齐的 RtlAllocateHeap 作为解决方法。
    • 没有必要亲自处理。你描述'Pack'的方式让你不清楚你是否理解它。 Pack 不是一个属性,它不能用来单独对齐任何东西。也许你可以看到我对这个问题的理解是错误的。
    • 当然,我不知道你的问题的答案(现在我理解正确了)。
    • 抱歉,我把它看得太个人化了:D。
    【解决方案2】:

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

    像这样:

    [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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-21
      • 2012-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-24
      • 1970-01-01
      • 2014-02-19
      相关资源
      最近更新 更多