7

I have written a VC++ dll. The declaration for one of the methods in the dll is as follows:

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

I use this dll in a C# code using P/Invoke. I make the declaration as:

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

and I call the function in the code as:

startIt(0);

Now, when this line is encountered, the compiler is throwing me this error:

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.

I cannot understand why is it throwing this error as the signature in both managed and unmanaged code are the same. Moreover, in my another machine, the same code is running perfectly in visual studio. So, this makes me think that the error thrown is mis leading.

Please help.

Thanks

Constantin
  • 27,478
  • 10
  • 60
  • 79
Jayesh
  • 3,891
  • 11
  • 55
  • 83

3 Answers3

14

When you p/invoke an external function, the calling convention used defaults to __stdcall. Since your function uses the __cdecl convention, you need to declare it as such:

[DllImport("Tracking.dll", EntryPoint = "startIt",
    CallingConvention = CallingConvention.Cdecl)]
public extern static void startIt(int number);
Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • Thanks that worked! However, I still wonder why didn't it throw the same error while working on Win7! – Jayesh Nov 13 '10 at 09:22
  • @James, it should have, unless Win7 performs special plumbing behind the scenes to switch to the correct calling convention. – Frédéric Hamidi Nov 13 '10 at 09:24
  • @James, did you use the exact same dll on Win7 or did you recompile it there? – Constantin Nov 13 '10 at 09:29
  • @Constatin Yeah, I had rebuild it on XP! – Jayesh Nov 13 '10 at 09:33
  • 2
    The difference between `stdcall` and `cdecl` is that with `stdcall` it's the responsibility of the called function to remove the parameters from the stack(which it usually does with `RET x` to move ESP by x) and with `cdecl` it's the responsibility of the caller. – CodesInChaos Nov 13 '10 at 09:39
  • @CodeInChaos, the function name decoration is also different. – Frédéric Hamidi Nov 13 '10 at 09:41
  • @James, regarding Win7 vs XP discrepancy: there is a "default calling convention" setting in Visual C++ and it could be different in your XP and Win7 builds (`__cdecl` on XP and `__stdcall` on Win7). – Constantin Nov 13 '10 at 15:14
  • @FrédéricHamidi what is an unbalanced stack? is it like a stack overflow? – Goku Dec 04 '18 at 03:49
6

Could you be missing CallingConvention=CallingConvention.Cdecl in your DllImport attribute?

Constantin
  • 27,478
  • 10
  • 60
  • 79
4

Constantin and Frederic Hamidi have answered this question correctly as to how to fix this problem. This can help avoid an eventual stack overflow. I have bitten by this several times myself. What is really at play here is that .NET 4 has enabled a managed debugging assistant for debug (not release) builds on 32 bit x86 machines (not 64 bit ) that checks for an incorrectly specified p/invoke call. This MSDN article details this : http://msdn.microsoft.com/en-us/library/0htdy0k3.aspx. Stephen Cleary deserves the credit for identifying this on this post: pinvokestackimbalance -- how can I fix this or turn it off?

Community
  • 1
  • 1
John Wigger
  • 904
  • 8
  • 10