2011-03-17 79 views
2

我的可执行文件调用了一些我自己编写的DLL。根据这些DLL使用的第三方C++库,我无法自由选择所有DLL的编译器设置。因此,在一些DLL中,_ITERATOR_DEBUG_LEVEL被设置为2(在调试版本中默认),但是在我的可执行文件_ITERATOR_DEBUG_LEVEL中,根据严重的性能问题,它被设置为0。如何将C++对象传递给具有不同_ITERATOR_DEBUG_LEVEL的DLL

当我现在将std::string传递给DLL时,只要DLL尝试将其复制到本地std :: string obj,应用程序就会崩溃,因为DLL中字符串对象的内存布局不同于在我的可执行文件中。到目前为止,我通过传递C字符串来解决这个问题。我甚至写了一个小类,它将一个std::map<std::string, int>转换为C-Data中的临时表示并将其转换为C-Data中的临时表示,以便将sich数据传递给DLL。这工作。

我该如何克服这个问题?我想传递更多不同的类和容器,并且由于几个原因,我不想与_ITERATOR_DEBUG_LEVEL = 2一起工作。

+0

摘要:bye bye OO ... – 2011-03-17 14:15:33

+0

完全没有 - 没有stl并不意味着没有OO。您可以使用不包含数据成员的类来创建抽象接口/适配器 - 只有纯虚拟方法。在这里,我发现了一篇有趣的文章:[代码项目:从DLL导出C++类](http://www.codeproject.com/KB/cpp/howto_export_cpp_classes.aspx#CppMatureApproach) – MacGucky 2011-03-17 14:37:17

+0

不,作为客户,您应该**需求**将第三方库编译为可用版本。或者被允许重新编译自己。这不是一个语言问题,这是一个业务问题。谁长期出售无法使用的图书馆? – 2011-03-17 14:40:47

回答

2

问题是,std :: string和其他容器是模板类。它们是在编译时为每个二进制生成的,所以在你的情况下它们的生成方式不同。你可以说它不是同一个对象。

要解决这个问题,你有几个解决方案,但他们都遵循相同的经验法则:不要在你的头文件代码中公开任何模板代码

您只能为此创建特定的接口,或者只是确保您的头文件不公开模板类型和函数。您可以在二进制文件中使用这些模板类型,但不要将其暴露给其他二进制文件。

接口中的std :: string可以被const char *替换。您仍然可以在系统中使用std :: string,只需在接口中请求const char *并使用std :: string :: c_str()来公开您的数据。

对于地图和其他容器,您必须提供允许外部代码操作内部地图的函数。像“Find(const char * key);”。

主要问题将与您的暴露类的模板成员。解决这个问题的一个方法是使用PImpl习惯用法:创建(或生成)一个API,头文件,只是公开可以用你的二进制文件完成的工作,然后确保API指向你的二进制文件中的真实对象。该API将用于外部但在您的库内部,您可以使用任何您想要的代码进行编码。 DirectX API和其他操作系统API以这种方式完成。

+0

如果你的图书馆有类似的来源于? – phandinhlan 2015-06-17 08:33:39

+0

@phandinhlan在这种情况下会出现什么问题?如果您考虑提供对内部成员的访问权限,那么只需使用受保护的访问者函数将这些成员存储在impl中。 – Klaim 2015-06-17 12:49:33

2

我对像_SECURE_SCL和_ITERATOR_DEBUG_LEVEL这样的标志有自己的经验,如果您尝试通过,它们必须一致一个stl对象跨dll badaries。 但是我认为你可以将一个stl对象传递给一个dll,它有一个较小的_ITERATOR_DEBUG_LEVEL ,因为你可以将一个stl对象在一个调试dll中实例化为一个在发布模式下编译的dll。

编辑07/04/2011 显然,Visual Studio 2010提供了一些检测ITERATOR_DEBUG_LEVEL之间不匹配的细节。我还没有观看视频。

http://blogs.msdn.com/b/vcblog/archive/2011/04/05/10150198.aspx

3

不建议使用的C++接口与复杂类型(STL ...)与第三方库,如果你让他们只为二进制或需要它们是从不同的编译特殊设置你的设置。

正如你写的 - 实现可能会因同一个编译器而异,具体取决于你的设置和不同的编译器,情况会变得更糟。

如果可能的话,用您的编译器和您的设置编译第三方库。

如果这是不可能的,您可以编写一个包装器DLL,它使用与第三方库相同的编译器和相同的设置进行编译,并为您提供一个C-Data接口。在你的项目中,你可以编写另一个包装类,这样你就可以使用STL对象进行函数调用,并将它们转换并转换为“后台”。