2

I'm attempting to use PInvoke to call an unmanaged C++ DLL and I'm getting errors (see below). Using depends.exe I can see the mangled name in the exported function list, hence the weird EntryPoint name. Although this exception appears, if I continue to Step Over while debugging, the function returns and ptr equals 1 and "Success" is printed.

I've tried some of the suggestions found in other posts, but nothing worked. I figured uint32_t is pretty self explanatory. I've tried changing the C# PInvoke signature to use long and ulong however the exception is still thrown and the value of ptr is a very large number. I've also tried setting CharSet and ExactSpelling properties for the DllImport attribute but that didn't seem to work either.

My question is, what am I doing that's causing an exception, and if I can't/shouldn't ignore the exception-how can that be done?

Unmanaged C++

MyClass.h

class __declspec(dllexport) MyClass
{
public:
   uint32_t runCommand(uint32_t start);
};

MyClass.cpp

uint32_t MyClass::runCommand(uint32_t start);
{
    uint32_t status = 1;
    return status;
}

Managed C#

P/Invoke Signature

[DllImport("myClass.dll", 
           EntryPoint = "?runCommand@MyClass@myClass@@QAEII@Z", 
           CallingConvention = CallingConvention.Cdecl)]
public static extern UInt32 runCommand(UInt32 baseAddress);

Usage

public static void Do()
{
    UInt32 a = 0xA000;
    UInt32 ptr = runCommand(a);
    Console.Write("Success!");
}

Error:

Managed Debugging Assistant 'PInvokeStackImbalance' has detected a problem in 'C:\Users...\TestApp.vshost.exe'.

Additional information: A call to PInvoke function 'TestApp!TestApp.CSMyClass::runCommand' 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.

Using Visual Studio 2015, and C# application is .NET Framework 4.6.

1 Answer 1

5

There is a mismatch in calling conventions, which causes the stack unbalance.

Since runCommand is a member function of MyClass, the calling convention used for it is not __cdecl, but __thiscall (note that there is an implicit "this" pointer passed as argument with non-static member functions of C++ classes).

You may want to either export a pure C interface function (not a C++ class member function) from your DLL for P/Invoke'ing, or you can use C++/CLI to build a tiny bridging layer between native and managed code, wrapping your C++ native class in a .NET managed class written in C++/CLI, and use that managed class wrapper from C#.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks. To reiterate to readers, if you come across this, and your scenario allows you to just turn the member function into a static member function, you can do this too. In the MyClass.h file, I changed the definition to static uint32_t runCommand(uint32_t start); and that got rid of the issue.
You're welcome. I haven't checked that in details (since I don't like exporting C++ classes from DLL interfaces), but that's probably because a static member function doesn't have the additional this pointer parameter.
That's exactly why. @Kevin, surely it's better to take this function outside of the class?
@DavidHeffernan I tried doing that in my actual code but it can't be done the way its setup. I get SEHExceptions, so I'm assuming I'll have to do a C++/CLI approach.
I don't see why that should be so. It should be viable through p/invoke if you wish.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.