2010-10-11 8 views
2

J'essaie de marshal correctement certaines structures pour un P/Invoke, mais je trouve un comportement étrange lors du test sur un système d'exploitation 64 bits.64 bits P/Invoke Idiosyncrasy

Je struct défini comme:

/// <summary>http://msdn.microsoft.com/en-us/library/aa366870(v=VS.85).aspx</summary> 
[StructLayout(LayoutKind.Sequential)] 
private struct MIB_IPNETTABLE 
{ 
    [MarshalAs(UnmanagedType.U4)] 
    public UInt32 dwNumEntries; 
    public IntPtr table; //MIB_IPNETROW[] 
} 

Maintenant, pour obtenir l'adresse de la table, je voudrais faire un appel Marshal.OffsetOf() comme ceci:

IntPtr offset = Marshal.OffsetOf(typeof(MIB_IPNETTABLE), "table"); 

Cela devrait être 4 - J'ai jeté les octets de la mémoire tampon pour confirmer cela ainsi que de remplacer l'appel ci-dessus par un 4 codé en dur dans mon arithmétique de pointeur, ce qui a donné des résultats corrects.

je reçois l'attendu 4 si j'instancier MIB_IPNETTABLE et réalise l'appel suivant:

IntPtr offset = (IntPtr)Marshal.SizeOf(ipNetTable.dwNumEntries); 

Maintenant, dans une séquence struct le décalage d'un champ doit être la somme des tailles des champs précédents, non? Ou est-ce que lorsque c'est une structure non gérée, le décalage est vraiment 8 (sur un système x64), mais devient 4 seulement après la magie de Marshalling? Est-il possible d'obtenir l'appel OffsetOf() pour me donner le décalage correct? Je peux boiter en utilisant des appels à SizeOf(), mais OffsetOf() est plus simple pour les structures plus grandes.

+0

Cette structure est traduite de manière incorrecte. En fait 'table' dans un tableau en ligne. –

Répondre

2

Dans une construction C/C++ 64 bits, le décalage de votre champ table serait de 8 en raison des exigences d'alignement (sauf si vous l'avez forcé autrement). Je soupçonne que le CLR fait la même chose pour vous:

Les membres de l'objet sont disposés successivement, dans l'ordre dans lequel ils apparaissent lorsque exportés vers la mémoire non géré . Les éléments sont disposés conformément à l'emballage spécifié au StructLayoutAttribute.Pack et peuvent être non adjacents.

vous pouvez utiliser WNAT cet attribut ou utiliser l'attribut LayoutKind.Explicit avec l'attribut FieldOffset sur chaque champ si vous avez besoin de ce niveau de contrôle.

+0

Merci de confirmer mes soupçons sur l'alignement non géré. La mise en page explicite avec FieldOffset est ce que je cherche. –