2010-06-08 11 views
2

Je dois appeler une DLL C++ à partir de mon programme C#. Je suis en train de le faire en utilisant PInvoke - tout fonctionne bien dans VS2005 \ 2008, mais après la migration vers VS 2010, je reçois cette exception:Pointeur de structure Marshal dans VS2010

PInvokeStackImbalance a été détecté Message: Un appel à la fonction PInvoke ' sampleFunc 'a déséquilibré la pile. Cela est probablement dû au fait que la signature PInvoke gérée ne correspond pas à la signature cible non gérée . Vérifiez que la convention d'appel et les paramètres de la signature PInvoke correspondent à la signature non gérée

C'est le prototype C++ d'origine:

typedef struct { 
    unsigned short field1; 
    unsigned short field2; 
} sInfo; 

_declspec(dllexport) int sampleFunc(sInfo *info, char *txt); 

et voici le code C#:

[StructLayout(LayoutKind.Sequential)] 
    struct SInfo 
    { 
     //[MarshalAs(UnmanagedType.U1)] //also tried with the MarshalAs attr. Didn't help. 
     public ushort field1; 
     //[MarshalAs(UnmanagedType.U1)] 
     public ushort field2; 
    }; 
[DllImport("sampleModule.dll", CharSet=CharSet.Ansi)] 
     public static extern int sampleFunc(ref SInfo info, [MarshalAs(UnmanagedType.LPStr)] string txt); 

Je l'ai essayé aussi avec IntPtr au lieu de l'arbitre sInfo, mais nous avons eu le même résultat ...

Toute aide sera appréciée,

Merci à tous!

Répondre

2

Difficile de voir comment cela aurait pu fonctionner avant. La déclaration C++ ne déclare pas la convention d'appel, la valeur par défaut est __cdecl sauf si elle est substituée dans le projet C++ avec l'option de compilation/Gz. Vous devez indiquer au marshaller P/Invoke:

[DllImport("sampleModule.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] 
    public static extern int sampleFunc(ref SInfo info, string txt); 
1

Cela a probablement à voir avec la façon dont vous emballez la structure. La taille par défaut du pack est 8, donc il pense probablement que vous avez trop d'octets. Essayez de régler la taille du pack 2 (16 bits aligné) et voir si cela aide:

[StructLayout(LayoutKind.Sequential, Pack=2)] 

Sinon, vous pouvez spécifier les décalages comme ceci:

[StructLayout(LayoutKind.Explicit)] 
public struct struct1 
{ 
    [FieldOffset(0)] 
    public ushort a; // 2 bytes 
    [FieldOffset(2)] 
    public ushort b; // 2 bytes 
} 

Here est une bonne référence sur l'emballage

+0

Cela ne peut pas être, un pointeur vers la structure est transmis. –

Questions connexes