C # P / вызвать выравнивание структуры

2

Я пытаюсь вызвать NtGetContextThread из С# на AMD64. Проблема в том, что структура CONTEXT для AMD64 должна быть выровнена по 16-байтовой границе, а когда я вызываю NtGetContextThread, я всегда получаю STATUS_DATATYPE_MISALIGNMENT. Я знаю, что С# может выровнять отдельные элементы структуры с помощью атрибута Pack, но, похоже, он не может выровнять всю структуру. Есть ли способ сделать это?

РЕДАКТИРОВАТЬ: просто для того, чтобы это было ясно, я не хочу выравнивать отдельных участников. Я хочу выровнять всю структуру.

Теги:
alignment
pinvoke

2 ответа

2

Из вашего вопроса неясно, полностью ли вы понимаете свойство Pack атрибута StructLayout. Для получения дополнительной информации см. Эту статью msdn.

Если я правильно вас понимаю, то, что вы ищете, это возможность однозначного выравнивания каждого члена структуры по отдельности. Если это ваша цель, вы можете сделать это, используя атрибуты 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-байтовыми границами. Для этой проблемы существуют обходные пути, но вы должны знать, что могут возникнуть такие проблемы.

  • 0
    Нет, это не то, что я хочу сделать. Я хочу выровнять всю структуру CONTEXT по 16-байтовой границе, а не по отдельным полям, как DECLSPEC_ALIGN. И я знаю, что делает свойство Pack, большое спасибо. В настоящее время я использую RtlAllocateHeap с 16-байтовым выравниванием в качестве обходного пути.
  • 2
    Там нет необходимости принимать это лично. То, как вы описываете «Пак», неясно, поняли ли вы это. Пакет не является атрибутом, и его нельзя использовать для индивидуального выравнивания чего-либо. Может быть, вы видите, как я неправильно понял вопрос.
Показать ещё 2 комментария
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;

Ещё вопросы

Сообщество Overcoder
Наверх
Меню