首页 > 解决方案 > 通过 Visual Studio 的 DLL 边界传递 std::string 的问题

问题描述

我有一个包含如下代码的 DLL:

class Info {
    int a
    int b
    int c
    std::string str1;
    std::string str2;
};

__declspec(dllexport) class C {
    Info getInfo();
}

我用 Visual Studio 2015 编译了这段代码,调用C::getInfo()在我的系统上运行得非常好。

现在其他人正在尝试使用 DLL,并且他也在使用 Visual Studo 2015。调用运行良好,但字符串不包含任何可访问的数据。甚至调试器也会报告“读取字符串字符时出错”,并且程序在尝试读取时崩溃。

还有一个类似的问题std::vector,我可以通过内联创建向量的代码来解决。

在我看来,这看起来像是另一个人正在使用不同的 STL 版本,或者编译器以某种方式产生了不同的内存布局std::string(尽管他声称使用默认设置)。

这可能吗?我看到 VS 2015 有不同的更新,我们可能没有安装相同的更新。

有什么建议可以解决这个问题吗?char*如果不显着破坏 API ,我就无法移动。大多数用户甚至不使用 Visual Studio(或 Windows),所以直到现在这还不是问题。

标签: c++visual-studiodllstldllexport

解决方案


这就是我害怕的生活。除非您拥有完全相同的编译器(包括 C++ 标准库)和编译器设置,否则这不能保证有效。从 C++ 标准的角度来看,我不相信即使这样也能保证工作。在 C++ 中构建 ABI 几乎是不可能的。在您的具体示例中,不能保证struct将使用相同的对齐特征构建。sizeof(std::string)差异很大,部分原因是短字符串优化甚至可以是编译器可配置的。

备择方案:

  1. 为您的导出函数和调用者分配和释放的 char* 样式接口使用 C 链接(参见 Windows API)。(永远不要在客户端分配内存并在 dll 中取消分配,反之亦然。)

  2. 确保库的用户可以从源文件构建它。考虑作为静态库而不是动态库进行分发,因为前者更容易使用。


推荐阅读