2009-08-11 2 views
2

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

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

ответ

2

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

+0

Нет, это * не * то, что я хочу сделать. Я хочу выровнять структуру * whole * CONTEXT на 16-байтовой границе, а не отдельные поля, такие как DECLSPEC_ALIGN. И я знаю, что делает свойство Pack, большое спасибо. В настоящее время я использую RtlAllocateHeap с выравниванием по 16 байт в качестве обходного пути. – wj32

+2

Нет необходимости принимать это лично. То, как вы описываете «Пакет», не ясно, понимаете ли вы это. Пакет не является атрибутом, и он не может использовать для индивидуального выравнивания. Может быть, вы можете увидеть, как я ошибался в этом вопросе. – Odrade

+1

И, конечно, я не знаю ответа на ваш вопрос (теперь, когда я это правильно понимаю). – Odrade

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; 

 Смежные вопросы

  • Нет связанных вопросов^_^