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

时间:2017-05-17 16:50:57

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

在处理C ++ / CLI项目以包装本机C ++ DLL时,我遇到了一个带有std::string的本机函数。如下所示:

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匹配。

不知道什么可能出错。我可以对本地API进行其他调用,这些调用不完全正确。

1 个答案:

答案 0 :(得分:1)

您使用的std::string的定义与用于编译本机C ++ DLL的定义之间可能存在差异。即使定义相同,本机DLL可能没有使用与您相同版本的C运行时,因此当您的DLL为std::string分配内存时,Native DLL将尝试调用{{ 1}}在它上面(当字符串在delete方法的末尾被销毁时),并且对readFile的调用将转到与分配对象不同的堆!

如果要使其工作,则必须使用与本机DLL上使用的完全相同版本的编译器。请注意,您将仅限于项目的Release版本,因为您没有使用调试运行时编译的本机DLL。

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

相关问题