2010-11-13 16 views
7

Napisałem dll VC++. Zgłoszenie o jednej z metod w DLL jest następujący:Niezbilansowany stos!

extern "C" _declspec(dllexport) 
void startIt(int number) 
{ 
    capture = cvCaptureFromCAM(number); 
} 

Używam tego dll w kod C# przy użyciu P/Invoke. Robię deklarację jako:

[DllImport("Tracking.dll", EntryPoint = "startIt")] 
     public extern static void startIt(int number); 

i wywołania funkcji w kodzie jak:

startIt(0); 

Teraz, kiedy spotyka się ten wiersz, kompilator rzuca mi ten błąd:

A call to PInvoke function 'UsingTracking!UsingTracking.Form1::startIt' has 
unbalanced the stack. This is likely because the managed PInvoke signature does 
not match the unmanaged target signature. Check that the calling convention 
and parameters of the PInvoke signature match the target unmanaged signature. 

Nie mogę zrozumieć, dlaczego powoduje to błąd, ponieważ podpis w kodzie zarządzanym i niezarządzanym jest taki sam. Co więcej, w mojej drugiej maszynie ten sam kod działa doskonale w visual studio. Więc to sprawia, że ​​myślę, że błąd jest źle prowadzony.

Proszę o pomoc.

Dzięki

+0

Czy jest to jeden z twoich maszyn x86 i drugi x64? –

+0

Nie, oba to x86. Właśnie ten uruchamia Win7 i inny XP – Jayesh

Odpowiedz

13

Po wywołaniu funkcji zewnętrznej użyto domyślnego calling convention do __stdcall. Ponieważ funkcja wykorzystuje konwencję __cdecl, trzeba zadeklarować ją jako takie:

[DllImport("Tracking.dll", EntryPoint = "startIt", 
    CallingConvention = CallingConvention.Cdecl)] 
public extern static void startIt(int number); 
+0

Dzięki, że zadziałało! Jednak nadal zastanawiam się, dlaczego nie rzucił tego samego błędu podczas pracy na Win7! – Jayesh

+0

@James, powinien, chyba że Win7 wykonuje specjalne instalacje za kulisami, aby przełączyć się na prawidłową konwencję wywoływania. –

+0

@ James, czy użyłeś dokładnie tego samego pliku dll na Win7, czy też dokonałeś ponownej kompilacji? – Constantin

6

Czy może brakuje CallingConvention=CallingConvention.Cdecl w swoim atrybutem DllImport?

+1

To był mój problem podczas debugowania tego problemu (po przejściu na .NET 4). 'stdcall' jest domyślnym, jeśli tego nie określisz! –

+0

Rozwiązało to również dla mnie po zmianie starego rozwiązania z .NET 2 na .NET 4) –

4

Constantin i Frederic Hamidi odpowiedziałeś poprawnie na to pytanie, jak rozwiązać ten problem. Może to pomóc uniknąć ewentualnego przepełnienia stosu. Pogryzłem przez to kilka razy sam. W rzeczywistości chodzi o to, że platforma .NET 4 włączyła zarządzany asystent debugowania do debugowania (nie wydania) na 32-bitowych maszynach x86 (nie 64-bitowych), które sprawdzają niepoprawnie określone wywołanie p/invoke. Ten artykuł MSDN wyszczególnia to: http://msdn.microsoft.com/en-us/library/0htdy0k3.aspx. Stephen Cleary zasługuje na uznanie za zidentyfikowanie tego na tym stanowisku: pinvokestackimbalance -- how can I fix this or turn it off?