pinvokestackimbalance – come posso risolvere questo problema o distriggersrlo?

Sono appena passato a vs2010 da vs2008. Esatta stessa soluzione, tranne che ora ogni singola chiamata a una dll C ++ produce un’eccezione ‘pinvokestackimbalance’.

Questa eccezione non viene licenziata nel 2008. Ho accesso completo alla DLL C ++ e all’applicazione chiamante. Non sembra che ci sia alcun problema con il pinvoke, ma questo problema sta rendendo imansible il debug di altri problemi; l’IDE si ferma costantemente per parlarmi di queste cose.

Ad esempio, ecco la firma C #:

[DllImport("ImageOperations.dll")] static extern void FasterFunction( [MarshalAs(UnmanagedType.LPArray)]ushort[] inImage, //IntPtr inImage, [MarshalAs(UnmanagedType.LPArray)]byte[] outImage, //IntPtr outImage, int inTotalSize, int inWindow, int inLevel); 

Ecco come appare sul lato C ++:

 #ifdef OPERATIONS_EXPORTS #define OPERATIONS_API __declspec(dllexport) #else #define OPERATIONS_API __declspec(dllimport) #endif extern "C" { OPERATIONS_API void __cdecl FasterFunction(unsigned short* inArray, unsigned char* outRemappedImage, int inTotalSize, int inWindow, int inLevel); } 

Qual è la differenza tra vs2010 e vs2008 che causerebbe il lancio di queste eccezioni? Dovrei aggiungere un diverso set di parametri alla direttiva DllImport?

Innanzitutto, capisci che il codice è sbagliato (e lo è sempre stato). “PInvokeStackImbalance” non è un’eccezione di per sé, ma un assistente di debug gestito. Era spento per impostazione predefinita in VS2008, ma molte persone non lo accendevano, quindi è triggersto per impostazione predefinita in VS2010. La MDA non funziona in modalità Release, quindi non si innescherà se si costruisce per il rilascio.

Nel tuo caso, la convenzione di chiamata non è corretta. DllImport valore predefinito di DllImport CallingConvention.WinApi , che è identico a CallingConvention.StdCall per il codice desktop x86. Dovrebbe essere CallingConvention.Cdecl .

Questo può essere fatto modificando la riga [DllImport("ImageOperations.dll")] per essere:

 [DllImport("ImageOperations.dll", CallingConvention = CallingConvention.Cdecl)] 

Per ulteriori informazioni, vedere questo riferimento MSDN

Per distriggersrlo:

  1. CTRL + ALT + E
  2. Sotto “Managed Debugging Assistants” deseleziona PInvokeStackImbalance.

Meglio risolvere questo problema non è molto difficile qui sto citando alcuni dei metodi, potrebbe essere lo stesso di alcuni dei miei amici menzionati sopra. Sto lavorando con un’applicazione Smartcard PCSC che trascorro circa una settimana, mi sono incazzato e molte modifiche hanno finalmente trovato le soluzioni.

Per me il suo lavoro con PInvoke Extension che ho installato per VS2010 è ansible scaricarlo qui http://www.red-gate.com/products/dotnet-development/pinvoke/

Scaricalo e installalo, chiudi visual studio e apri di nuovo l’estensione sulla barra dei menu. inserisci la descrizione dell'immagine qui

Se l’errore è dovuto alla firma non corrispondente, è sufficiente fare clic su PInvoke.net> Inserisci firme PInvoke

La nuova finestra apparirà come sotto inserisci la descrizione dell'immagine qui

Inserisci il nome della DLL e clicca su Cerca puoi vedere tutte le funzioni di quella DLL nella finestra dei risultati di ricerca, Clicca sulla funzione otterrai una firma per quella particolare Funzione.

Usa quella firma e devi modificare i tuoi programmi in base a quella Firma, principalmente il tipo di dati.

Questo risolve il mio problema, potresti avere diversi problemi come callConvention o altri attributi che devi specificare durante l’importazione di dll.

Felice codifica Stai bene!

Ho avuto questo problema anche quando si utilizza VS2010. Che cos’è: Visual Studio ha come valore predefinito un codice a 64 bit per “qualsiasi CPU”. I puntatori alle variabili (ad esempio le stringhe) ora diventano 64 bit quando si chiamano le DLL esterne, dove tutte le Dll affidabili e affidabili utilizzano puntatori a 32 bit.

Non dare per scontato che ci sia qualcosa di sbagliato con il tuo DLL, non c’è.

Cambia le tue impostazioni VS per generare codice X86 come questo (versioni espresse di C #)

  1. vai su Strumenti -> Opzioni.
  2. Nell’angolo in basso a sinistra della finestra di dialogo Opzioni, seleziona la casella “Mostra tutte le impostazioni”.
  3. Nella vista ad albero sul lato sinistro, seleziona “Progetti e soluzioni”.
  4. Nelle opzioni a destra, seleziona la casella “Mostra le configurazioni di build avanzate”.
  5. Clicca OK.
  6. Vai a Build -> Configuration Manager …
  7. Nella colonna Piattaforma accanto al tuo progetto, fai clic sulla casella combinata e seleziona “”.
  8. Nell’impostazione “Nuova piattaforma”, scegli “x86”.
  9. Clicca OK.
  10. Clicca Chiudi.

Noto anche che, anche se i computer sono raddoppiati al potere ogni 12 mesi, il mio attuale computer con 1gig di RAM, non sembra più veloce del mio primo 486 con 4 Meg. Non preoccuparti di usare il codice a 64 bit, non sarà più veloce o migliore perché è costruito su un’enorme torre ingombrante e orientata agli oggetti.

Ho provato a chiamare dll con CallingConvention è ThisCall e ha funzionato per me. Ecco il mio codice che funziona con BLOB MS Sql Server.

 [DllImport("sqlncli11.dll", SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.ThisCall)] private static extern SafeFileHandle OpenSqlFilestream( string FilestreamPath, UInt32 DesiredAccess, UInt32 OpenOptions, byte[] FilestreamTransactionContext, UInt32 FilestreamTransactionContextLength, Int64 AllocationSize); 

Maggiori informazioni su: https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.callingconvention(v=vs.110).aspx