PInvoke .net / C++ dll not working.

MatthewOsosky
MatthewOsosky used Ask the Experts™
on
I have probably the most basic setup possible, need to know why it is not working. A very simple C++ dll with a single method called Toast, one int in, with a return of int.

I also have a C# wrapper class with DLLImport function referencing the same

However when I run the deal, I get a nasty error about an unbalanced stack. Like the signature and return type of the wrapper don't match the DLL. Also if you continue through the exception the result comes back as expected.

Why would I be getting this message since the signations match? (return of int and one int in)
//DLL CODE

__declspec(dllexport) int Toast(int x)
{
	return x + 100;
}

//.NET
public static class Wrapper
    {
        [DllImport("File.dll", EntryPoint = "?Toast@@YAHH@Z")]
        public static extern Int32 WR_TOAST(Int32 x);

    }

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2012
Top Expert 2008

Commented:
If this code is on a 64-bit machine, then Int32 would not be correct.  You can use 'int', instead 'Int32'.
Commented:
It makes sense also to  extern "C" for this function:

extern "C" __declspec(dllexport) int Toast(int x)

So the EntryPoint will look normal


public static class Wrapper
    {
        [DllImport("File.dll", EntryPoint = "Toast")]
        public static extern int WR_TOAST(Int x);
    }

MSDN. C# Programmer's Reference. Platform Invoke Tutorial
http://msdn.microsoft.com/en-us/library/aa288468(VS.71).aspx

This tutorial contains an example with "puts" function from the C Run-Time Library that looks almost as your function.

Author

Commented:
Interestingly, my mahcine is 64bit but that was not the problem. In fact the VS compilers seem to always make in Int 32 bits wide no matter. In the .Net frame build you can explicitly set a 64bit build and the size of and Int is still 32 bits. I tried using all sizes of ints on the .Net side, Int64, Int32, Int16 etc... Nothing chnaged the problem.

What I found was that the default calling convention in c++ is cdecl, while the DLLImport has a default calling convention of stdcall (or WINAPI which makes sense when you think about it). The solution was to either set the calling convention in the c++ ode to __stdcall, or to set the calling convention parameter in DLLImport to Cdecl.

pgnatyuk, thanks for that tip. I knew there was a way to do that and at the same time was wondering why the exmaples had that syntax.

Thanks,
Matthew


//SET IN .NET
[DllImport("SoundEngine.dll", EntryPoint = "?Toast@@YGHH@Z", CallingConvention = CallingConvention.Cdecl)]

//OR SET In C++
__declspec(dllexport) int __stdcall Toast(int x)
{
	return x + 100;
}

Open in new window

Author

Commented:
I tried to give pgnatyuk 200 points for his input but it did not stick.

Commented:
:)
So I will press "Object" below and you will have possibility to accept your comment as the solution and my as an assisted

Author

Commented:
Damn it, it did it again. These new changes suck.

Author

Commented:
x

Author

Commented:
x

Commented:
Try again

Commented:
Even better. :)
Thanks.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial