Я пытаюсь вызвать NtGetContextThread из С# на AMD64. Проблема в том, что структура CONTEXT для AMD64 должна быть выровнена по 16-байтовой границе, а когда я вызываю NtGetContextThread, я всегда получаю STATUS_DATATYPE_MISALIGNMENT
. Я знаю, что С# может выровнять отдельные элементы структуры с помощью атрибута Pack, но, похоже, он не может выровнять всю структуру. Есть ли способ сделать это?
РЕДАКТИРОВАТЬ: просто для того, чтобы это было ясно, я не хочу выравнивать отдельных участников. Я хочу выровнять всю структуру.
Из вашего вопроса неясно, полностью ли вы понимаете свойство 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-байтовыми границами. Для этой проблемы существуют обходные пути, но вы должны знать, что могут возникнуть такие проблемы.
Единственный способ, которым я нашел это, - это выделить указатель и пойти небезопасно.
Вот так:
[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;