对 PInvoke 函数 [函数名称] 的调用使堆栈不平衡

A call to PInvoke function [function name] has unbalanced the stack

我正在尝试使用 PInvoke 调用非托管 C++ DLL,但出现错误(见下文)。使用 depends.exe 我可以在导出的函数列表中看到损坏的名称,因此是奇怪的 EntryPoint 名称。虽然出现了这个异常,但如果我在调试时继续Step Over,函数returns和ptr等于1并且打印“Success”。

我尝试了其他帖子中的一些建议,但没有任何效果。我认为 uint32_t 是不言自明的。我已经尝试更改 C# PInvoke 签名以使用 longulong,但是仍然抛出异常并且 ptr 的值是一个非常大的数字。我还尝试为 DllImport 属性设置 CharSetExactSpelling 属性,但这似乎也不起作用。

我的问题是,我在做什么导致了异常,如果我不能t/shouldn忽略异常——那怎么办?

非托管 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;
}

托管 C#

P/Invoke签名

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

用法

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

错误:

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.

使用 Visual Studio 2015,C# 应用程序是 .NET Framework 4.6。

调用约定不匹配,导致堆栈不平衡。

由于 runCommandMyClass 成员函数 ,因此使用的调用约定是 而不是 __cdecl,但 __thiscall(请注意,有一个隐含的“this”指针作为参数传递给 C++ classes 的非静态成员函数)。

您可能想要从您的 DLL 中导出一个 纯 C 接口函数(不是 C++ class 成员函数)以进行 P/Invokeing,或者您可以使用 C++/CLI 在本机代码和托管代码之间构建一个微小的桥接层,将您的 C++ 本机 class 包装在 .NET 托管 class 中编写C++/CLI,并使用来自 C# 的托管 class 包装器。