Click here to Skip to main content
15,923,083 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I have a C++ dll with the following function -

SQL
_declspec(dllexport) double _stdcall Spread (double high, double low)
{ return high - low;  }


When I run dumpbin I see that it is there -

2 0001103C Spread = @ILT+55(?Spread@@YANNN@Z)


And I define my C# import as -

C#
[DllImport(@"C:\MyDll.dll", EntryPoint="Spread")]
        static extern double Spread(double high, double low);



However calls to it as below fail -
MessageBox.Show(Spread(2.3, 3.3).ToString());


The error message is -

A call to PInvoke function 'myapp!myapp.Form1::Spread' 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.

What could be wrong with this?
Posted

Since you can't change the prototype in the C++ dll, then I'm assuming you didn't compile that dll and don't actually know how it was compiled.

So how do you know that the function was actually compiled with __stdcall ??

Just because you have a header file that says that, doesn't mean that that header file was the one that the dll was compiled with.

The "unbalanced" message pretty much means that you've mixed __stdcall and __cdecl or something like that. In one case the caller is supposed to clean up the stack, in the other the callee is supposed to. If you mix them up you end up with either neither caller or callee cleaning up the stack or both of them doing it -- in either case you'd get the unbalanced message.

See:

http://msdn.microsoft.com/en-us/library/984x0h58(v=VS.90).aspx[^]

If __stdcall isn't working, then the most likely scenario is that the C++ dll was actually compiled with __cdecl semantics.

Try that first, if it doesn't work try the other calling conventions listed. It really is only going to be the calling convention attribute that is a problem, so find the one it was really compiled with via trial and error (or stop in the debugger and examine the object code and see what stack clean up the callee is actually doing).
 
Share this answer
 
Comments
James Brown654321 30-Jun-11 10:14am    
Many thanks. I have found that this is it and making the following change resolves the issue.

[DllImport(@"C:\MyDll.dll", EntryPoint="Spread", CallingConvention=CallingConvention.Cdecl)] static extern double Spread(double high, double low);

Note the CallingConvention.Cdecl. I do have access to the source which is __stdcall however it only works when the C# expects __cdecl. That seems a bit odd.
Your DllImport attribute needs more properties to be set. I don't know which ones (or what their values should be), but I'm sure you can find the answer on google.
 
Share this answer
 
Comments
James Brown654321 30-Jun-11 8:51am    
Unfortunately I've already done no end of searching on google relating to this. I was posting hoping that someone with a complete answer would post.
#realJSOP 30-Jun-11 9:00am    
Voting the only answer you've received so far with a 1 is no way to convince me to keep trying to help. Besides, you didn't mention that you'd already googled your ass off.
James Brown654321 30-Jun-11 9:02am    
Thanks for your efforts anyhow. While helpful in some ways, the problem with incomplete answers is the question is then marked as 'answered' and may miss the attention of someone who has a complete answer. I hope that makes sense.
#realJSOP 30-Jun-11 9:10am    
I didn't say to mark it as the answer. I was merely disputing the 1-vote.
Try this on your prototype:

C#
static extern "C" int _cdecl Spread(double high, double low);
 
Share this answer
 
v2
Comments
James Brown654321 30-Jun-11 9:02am    
Thanks - unfortunately I can't change the prototype. I'm hoping this isn't a show stopper.
#realJSOP 30-Jun-11 9:04am    
I'm talking about the one in your C# code - NOT the dll.
James Brown654321 30-Jun-11 9:22am    
Unfortunately C# isn't recognising the "C" part of the above. Thanks anyhow.
#realJSOP 30-Jun-11 11:24am    
Then try setting the CallingConvention property in the DLLImport attribute - same deal (the code I gave you may have only applied to older versions of .Net).
James Brown654321 30-Jun-11 11:33am    
Please outline which versions of .Net supported "C"?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900