zoukankan      html  css  js  c++  java
  • DLL中导出STL模板类的问题

    接上一篇。

    上一篇的dll在编译过程中一直有一个警告warning C4251: ‘CLASS_TEST::m_structs’ : class ‘std::vector<_Ty>’ needs to have dll-interface to be used by clients of class ,百

    度之才发现是因为DLL中导出了STL中的类,二STL中的类默认是没有导出的,因此报告这个警告。

    程序中消除warning有两种方法:

    消极一点不去理他,反正不是error;

    积极一点,则想办法去掉。去掉又用两种方法:一种使用#pragma warning(disable: xxxx),眼不见,心不烦;另外就是找出解决问题的办法了。在头文件中,定义宏

    #ifdef DLL_EXPORT
    #define DLL_API __declspec(dllexport)
    #else
    #define DLL_API __declspec(dllimport)
    #endif
    

    搜索之,得到解决办法,修改后代码如下:

    class DLL_API dllBase
    {
    public:
        dllBase ( void );
        ~dllBase ( void );
        int get();
    private:
        static int base;
        template class DLL_API allocator< string >;
        template class DLL_API vector<string, allocator< string > >;
        vector<string> m_list;
    };

    可是这样编译又出问题了,error C2252: an explicit instantiation of a template can only occur at namespace scope。继续搜索之,说是应该吧上面的两句话放到类的外面

    再次试之,成功了,代码如下

    template class DLL_API allocator< string >;
    template class DLL_API vector<string, allocator< string > >;
    class DLL_API dllBase
    {
    public:
        dllBase ( void );
        ~dllBase ( void );
        int get();
    private:
        static int base;
        vector<string> m_list;
    };

    注:因为STL中只有vector可以直接导出,所以该方法成功了,若是将vector换成List,则依然会继续报告C4251错误,暂时还不知道怎么解决。

    虽然可以使用了,但是每次都在类前面写入那么一大堆东西,看着就有点烦,于是乎发现了一篇非常强大的日志,在其中发现了一个比较好的办法来解决这个问题,具体就不写了。

    但是使用它定义的带参数的宏可以比较方便的修改。

    代码如下:

    #define DLL_STL_LIST( STL_API, STL_TYPE ) 
        template class STL_API std::allocator< STL_TYPE >; 
        template class STL_API std::vector<STL_TYPE, std::allocator< STL_TYPE > >;
    
    DLL_STL_LIST ( DLL_API, string );
    
    class DLL_API dllBase
    {
    public:
        dllBase ( void );
        ~dllBase ( void );
        int get();
    private:
        static int base;
        vector<string> m_list;
    };

    参考的另一篇博客:

    1:情况一
    如果类的定义里面仅含有 编译器内置的类型变量, int, float 等等. 或者成员函数仅使用了这些变量作为参数, 那么很简单.
    直接
    class __declspec(dllexport) YourClass

    {
    }
    就行了.

    2:情况二
    如果类内部使用了别的类, 那么别的类最好也导出, 不然, 首先编译的时候会出现编译警告:
    warning C4251: needs to have dll-interface 
    意思是,你使用另外的一些类型/接口, 但是这些类型或接口没有导出. 当你的client使用这些类型/接口的时候, 会出错!
    class __declspec(dllexport) YourClass

    {
       YourAnatherClass m_data; // 这里会 出现 warning 4251. 如果YourAnatherClass 没有导出的话.
    }
    解决办法就是: 在YourAnatherClass定义的地方加上
    class __declspec(dllexport) YourAnatherClass 
    {
    }
    如上, 当你的YourAnatherClass没有导出的时候, dll的使用方会出现链接错误

    3:情况三
    当类的内部使用了STL模板的时候, 也会出现C4251警告, 情况会有所不同
    class __declspec(dllexport) YourClass

    {
       vector m_data; // 这里会 出现 warning 4251. 因为vector类型没有被导出
    }
    上面的使用模板(无论是stl模板,还是自定义模板)的代码,编译dll时会出现C4251警告, 但是dll的使用方, 却不会出现链接错误!!!
    这个因为, dll的使用方那里也有一套模板的定义, 当他们使用那个vector的时候, 虽没有导出, 但是用户自己也有一套STL模板(或者是自定义的模板),用户会利用自己的模板实例化这个dll中没有导出的东西!

    所以, 对于因为使用STL(或模板)出现的c4251警告, 关闭之即可
    #pragma warning(push)
    #pragma warning(disable:4251)
    //your declarations that cause 4251
    #pragma warning(pop)

    若想不使用通过关闭警告的方式关闭警告, 那么就这样

    1)对于用户自定义的模板
       template class DLLImportExportMacro SomeTemplate;
       SomeTemplate y;
    2)对于STL的模板
    template class DLL_API allocator< string >;

    template class DLL_API vector<string, allocator< string > >;

    vector<string> m_data;

  • 相关阅读:
    SQLServer执行大脚本文件时,提示“无法执行脚本没有足够的内存继续执行程序 (mscorlib)”
    SQLServer临时库文件太大,迁移tempdb数据库
    SQL Server设置数据库为状态为只读
    微信企业号应用
    前端不错的网站
    模拟桶排序
    记录javascript 验证字符串布尔类型 及url 参数获取
    JS表单设置值
    C#标准响应数据
    C# Like参数化 小记
  • 原文地址:https://www.cnblogs.com/duboway/p/3332057.html
Copyright © 2011-2022 走看看