c++ - 从 C++/CLI 调用 DLL 函数时的 PInvokeStackImbalance

标签 c++ .net visual-studio-2012 dll c++-cli

在处理 C++/CLI 项目以包装 native C++ DLL 时,我遇到了一个接受 std::string 的 native 函数。类似于以下内容:

class NativeApi
{
public:
  ErrorCode readFile(std::string filename = "path.csv");
};

在我的托管包装器实现中,我分配了一个新的本地类实例并调用了这个函数:

ref class ManagedApi
{
private:
  NativeApi *api;
public:
  ManagedApi(): api(new NativeApi()) { }
  void Read()
  {
    api->readFile("apath.csv") // or with nothing to use default value
  }
}

当我运行它时,我收到 MDA PinvokeStackImbalance 提示此调用使堆栈不平衡。我很惊讶,因为我唯一一次获得此 MDA 是在调用约定不匹配时来自 C#。我从未见过这种情况发生在 C++/CLI 中,大概所有的匹配都是由编译器自动完成的。

有没有人见过这个?谷歌搜索是空的。我查看了 DLL 签名,它看起来像这样:

?readFile@NativeApi@@QAE?AW4ErrorCode@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z

这告诉我函数在那里,并将 basic_string 作为唯一参数,它应该匹配标准 std::string typedef。

不知道可能出了什么问题。我可以对不涉及字符串的 native API 进行其他调用。

最佳答案

您正在使用的 std::string 的定义与用于编译 native C++ DLL 的定义之间可能存在差异。即使定义相同, native DLL 也可能没有使用与您相同版本的 C 运行时,因此当您的 DLL 为 std::string 分配内存时, native DLL将尝试对其调用 delete(当字符串在 readFile 方法结束时被销毁时),并且对 delete 的调用将会继续与用于分配对象的堆不同!

如果你想让它工作,你必须使用与在 native DLL 上使用的编译器完全相同的版本。请注意,您将仅限于项目的发布版本,因为您没有使用调试运行时编译的 native DLL。

解决此问题的正确 方法是在跨 DLL 边界调用时使用原始类型(在本例中为 wchar_t*)。如果您可以请求更改 native DLL,我会这样做。如果只使用原始类型,那么使用不同的运行时就没有问题,一切都会按应有的方式工作。

关于c++ - 从 C++/CLI 调用 DLL 函数时的 PInvokeStackImbalance,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44030710/

相关文章:

c++ - 还在获取重复值?

c# - 通过任何字符串属性实现搜索的通用谓词

asp.net-mvc - 在 VS 2012 中创建 MVC4 项目时出现 NuGet 错误

.net - Windows 7 和 8 中的不同 .NET 4.5?

visual-studio-2012 - CMake - 使用/MT 而不是/MD 编译

c++ - 是否可以在前瞻中使用 'Repeats' 来 boost :regex?

c++ - Windows 服务程序中退出函数的作用

c++ - 在if语句中优化/减少条件表达式

c# - 模拟 Networkstream.Read

c# - 使用 Android 手机浏览器从 Asp.net 网站下载 .apk 时出错