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

标签 c# c++ pinvoke unmanaged

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

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

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

非托管 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/调用签名

[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++ 类的非静态成员函数的参数传递)。

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

关于c# - 对 PInvoke 函数 [函数名称] 的调用使堆栈不平衡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40158240/

相关文章:

c# - Linq - 不以前缀范围内的任何前缀开头

c++ - 如何在 IOS 应用程序 (OpenGL) 中放置 href 链接

c++ - 如何在 QT 中使用 DEBUG 对齐日志文件中的数据?

c# - 在 C# 中存储对对象的引用

c# - 确定累积点的起点

c# - 如何访问 UWP 中的当前应用程序文件夹?

c++ - 真值表到位表达式

c# - P/Invoke 调用 CreateEnvironmentBlock 最多需要 30 秒?

c# - 将指向结构数组指针的指针从 C# 传递到 C++

C# 性能 - 使用不安全指针代替 IntPtr 和 Marshal