Llamada PInvokeStackImbalance C#a la función C++ no administrada
visual-studio-2010 dllimport (5)
Después de cambiar a VS2010, el asistente de depuración gestionada muestra un error sobre una pila no balanceada desde una llamada a una función C ++ no gestionada desde una aplicación C #.
Los sospechosos habituales no parecen estar causando el problema. ¿Hay algo más que deba verificar? La aplicación C ++ dll y C # creadas por VS2008 nunca tuvo un problema, ni errores extraños o misteriosos, sí, sé que eso no significa mucho.
Estas son las cosas que se controlaron:
- El nombre dll es correcto.
- El nombre del punto de entrada es correcto y se ha verificado con depends.exe: el código tiene que usar el nombre destruido y lo hace.
- La convención de llamadas es correcta.
- Los tamaños y tipos parecen ser todos correctos.
- El juego de caracteres es correcto.
- No parece haber ningún problema después de ignorar el error y no hay ningún problema cuando se ejecuta fuera del depurador.
DO#:
[DllImport("Correct.dll", EntryPoint = "SuperSpecialOpenFileFunc", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true)]
public static extern short SuperSpecialOpenFileFunc(ref SuperSpecialStruct stuff);
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct SuperSpecialStruct
{
public int field1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string field2;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string field3;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string field4;
public ushort field5;
public ushort field6;
public ushort field7;
public short field8;
public short field9;
public uint field10;
public short field11;
};
C ++:
short SuperSpecialOpenFileFunc(SuperSpecialStruct * stuff);
struct SuperSpecialStruct
{
int field1;
char field2[256];
char field3[20];
char field4[10];
unsigned short field5;
unsigned short field6;
unsigned short field7;
short field8;
short field9;
unsigned int field10;
short field11;
};
Aquí está el error:
El asistente de depuración administrado ''PInvokeStackImbalance'' detectó un problema en ''Ruta de la aplicación administrada''.
Información adicional: una llamada a la función PInvoke ''SuperSpecialOpenFileFunc'' ha desequilibrado la pila. Esto es probable porque la firma de PInvoke administrada no coincide con la firma de destino no administrada. Compruebe que la convención de llamada y los parámetros de la firma PInvoke coinciden con la firma no administrada de destino.
Como se menciona en el comentario de Dane Rose , puede usar __stdcall
en su función C ++ o declarar CallingConvention = CallingConvention.Cdecl
en su DllImport
.
Esta es la respuesta que resuelve mi problema.
Es bueno. Actualizar la función definir de la siguiente manera:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
Funciona bien.
Especifica stdcall en C # pero no en C ++, una falta de concordancia aquí dará lugar a que la función y los argumentos de invocación de la persona que llama salgan de la pila.
Por otro lado, hay un conmutador de compilador que activará stdcall como la convención de llamada predeterminada, (-Gz) ¿está utilizando eso?
O prueba esto en tu C ++
short __stdcall SuperSpecialOpenFileFunc(SuperSpecialStruct * stuff);
No especifica relleno en su declaración de C # de la estructura, pero no en la versión de C ++. Dado que está mezclando matrices de caracteres que no son todos múltiplos de cuatro y un número impar de cortos de 2 bytes, el compilador probablemente esté insertando relleno dentro de la estructura y agregue el extremo.
Intente envolver la estructura en un #pragma pack
para garantizar que no haya relleno.
#pragma pack(push)
#pragma pack(1)
// The struct
#pragma pack(pop)
Tuvo el mismo problema que el descrito: aplicación C ++ no administrada que funcionó perfectamente durante años. Cuando nos actualizamos a VS2010, comenzamos a recibir mensajes PInvokeStackUnbalanced.
agregar "__stdcall" a la firma de C ++ como se describió anteriormente hizo que el problema desaparezca.