在处理 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/