为了账号安全,请及时绑定邮箱和手机立即绑定

从DLL导出包含std ::对象(矢量,地图等)的类

从DLL导出包含std ::对象(矢量,地图等)的类

C++
叮当猫咪 2019-11-26 13:01:30
我正在尝试从包含诸如std :: vectors和std :: strings之类的对象的DLL中导出类-整个类通过以下方式声明为dll导出:    class DLL_EXPORT FontManager{问题是对于复杂类型的成员,我会收到以下警告:警告C4251:“ FontManager :: m__fonts”:类“ std :: map <_Kty,_Ty>”需要具有“ FontManager”类的客户端使用dll接口,并带有[_Kty = std :: string,_Ty = tFontInfoRef ]我可以通过以下警告类声明来删除某些警告,即使我没有更改成员变量本身的类型也是如此:template class DLL_EXPORT std::allocator<tCharGlyphProviderRef>;template class DLL_EXPORT std::vector<tCharGlyphProviderRef,std::allocator<tCharGlyphProviderRef> >;std::vector<tCharGlyphProviderRef> m_glyphProviders;看起来当成员被编译时,前向声明“注入”了DLL_EXPORT,但是它安全吗?当客户端编译此标头并在其一侧使用std容器时,它是否真的更改了任何内容?它会在将来使用这种容器DLL_EXPORT(并且可能不是内联吗?)吗?它真的解决了警告试图警告的问题吗?我是否应该担心此警告,还是最好在这些结构的范围内将其禁用?客户端和dll将始终使用相同的库和编译器集构建,而这些仅是标头类。我将Visual Studio 2003与标准STD库一起使用。----更新----尽管我认为答案很笼统,但我想将目标更多地作为目标,在这里我们谈论的是std容器和类型(例如std :: string)-也许问题确实是:我们是否可以通过相同的库标头禁用对客户端和dll都可用的标准容器和类型的警告,并像对待int或任何其他内置类型一样对待它们?(这似乎确实对我有利。)如果可以,那么在什么条件下我们可以做到这一点?还是应该禁止使用此类容器,或者至少要格外小心,以确保没有赋值运算符,复制构造函数等会内联到dll客户端中?总的来说,我想知道您是否设计一个具有此类对象的dll接口(例如,使用它们将东西作为返回值类型返回给客户端)是一个好主意,为什么?我想拥有这个功能的“高级”界面...也许最好的解决方案是Neil Butterworth建议的-创建静态库?C ++ Visual Studio DLL
查看完整描述

3 回答

?
一只甜甜圈

TA贡献1836条经验 获得超5个赞

该警告告诉您DLL的用户将无法跨DLL边界访问您的容器成员变量。明确导出它们使它们可用,但这是一个好主意吗?

通常,我会避免从您的DLL中导出标准容器。如果您完全可以保证您的DLL将与相同的运行时和编译器版本一起使用,则将是安全的。您必须确保使用相同的内存管理器释放在DLL中分配的内存。否则,充其量只能在运行时声明。

因此,请勿直接跨DLL边界公开容器。如果需要公开容器元素,请通过访问器方法公开。在您提供的情况下,将接口与实现分开,并在DLL级别公开接口。您对std容器的使用是DLL客户端不需要访问的实现细节。

或者,执行Neil的建议并创建一个静态库而不是DLL。您将失去在运行时加载库的能力,并且库的使用者必须在更改库时随时重新链接。如果您可以忍受这些妥协,那么静态库至少可以使您摆脱这个问题。我仍然认为您不必要地公开了实现细节,但这对您的特定库可能有意义。


查看完整回答
反对 回复 2019-11-26
?
慕慕森

TA贡献1856条经验 获得超17个赞

我发现处理这种情况的最佳方法是:


创建您的库,并使用库名称中包含的编译器和stl版本对其进行命名,就像boost库一样。


例子:


-用于dll版本的FontManager-msvc10-mt.dll,特定于MSVC10编译器,默认为stl。


-用于dll版本的FontManager-msvc10_stlport-mt.dll,特定于MSVC10编译器,带有stl端口。


-用于dll版本的FontManager-msvc9-mt.dll,特定于MSVC 2008编译器,具有默认的stl


-libFontManager-msvc10-mt.lib,用于静态lib版本,特定于MSVC10编译器,具有默认stl。


按照这种模式,您将避免与不同的stl实现相关的问题。请记住,vc2008中的stl实现与vc2010中的stl实现不同。


使用boost :: config库查看示例:


#include <boost/config.hpp>


#ifdef BOOST_MSVC

#  pragma warning( push )

#  pragma warning( disable: 4251 )

#endif


class DLL_EXPORT FontManager

{

public:

   std::map<int, std::string> int2string_map;

}


#ifdef BOOST_MSVC

#  pragma warning( pop )

#endif


查看完整回答
反对 回复 2019-11-26
  • 3 回答
  • 0 关注
  • 569 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信