std :: string可以通过DLL边界传递值吗?

时间:2014-05-12 15:00:11

标签: c++ visual-studio dll stdstring

std :: string是否可以通过不同版本的Visual Studio构建的DLL之间的DLL边界值传递?

2 个答案:

答案 0 :(得分:4)

不,因为模板化代码是按模块单独生成的。

因此,当您的EXE实例化std::string并将其传递给DLL时,DLL将开始使用完全不同的实现。结果是完全混乱,但它通常排序几乎起作用,因为实现非常相似,或者很难检测到混乱,因为它是某种微妙的堆损坏。

即使它们都使用相同版本的VS构建,但它非常不稳定/脆弱,我不推荐它。使用模块之间的C风格接口(例如,COM),或者只是不使用DLL。

此处有更详细的解释:Creating c++ DLL without static methods

在这里:How can I call a function of a C++ DLL that accepts a parameter of type stringstream from C#?

答案 1 :(得分:0)

通常,您不能混合使用不同编译器构建的二进制代码,其中包括同一编译器的不同版本(甚至可以包含使用不同命令行选项调用的相同编译器),因此您要尝试执行的操作的答案是一个明确的" No"。

原因是不同的编译器可能提供std :: string的不同实现。例如,一个实现可以具有固定的静态缓冲区,而另一个版本没有,这已经导致不同的对象大小。还有许多其他东西可以使接口不兼容,比如底层分配器,内部表示。由于名称损坏或不同的私有API,某些内容已经无法链接,这两者都可以保护您不会出错。

一些注意事项:

  • 即使你没有通过值传递对象但是通过引用,被调用的代码可能对这些对象的外观有不同的看法。
  • 类型由编译器提供也没有关系,即使您自己定义了类并使用不同版本的类定义编译了两个DLL,您也会遇到问题。此外,如果您更改标准库实现,则也会使二进制文件不兼容。
  • 其他代码在DLL中并不重要,它也适用于同一个可执行文件或DLL中的代码,尽管更改时的头文件和自动重新编译使得这种情况不太可能发生。
  • 特别是对于MS Windows,您还有一个调试堆和一个发布堆,并且一个内存中分配的内存不能返回给另一个。出于这个原因,你经常有两个DLL,一个带有' d'后缀(调试版)和一个没有。这种情况下编译器设置已经影响了兼容性,但你可以使用提供两个版本的DLL的并行方法来解决这个问题。
  • 在某种程度上,类似的问题也出现在C代码中,编译器必须同意例如结构布局和调用约定。由于更大的年龄和更低的复杂性,不同的C编译器实际上是兼容的。这也被认为是C中的必要特征,而不是C ++。