warning C4251 needs to have dll-interface解决办法

本文介绍了解决VS2005中C4251警告的方法,该警告出现在使用STL的DLL项目中。文章详细解释了如何通过导出特定模板来消除警告,并提供了针对不同情况的解决方案。
部署运行你感兴趣的模型镜像

转载地址:

http://wxohyer.wordpress.com/2010/04/16/warning-c4251-needs-to-have-dll-interface%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95/

程序中消除warning有两种方法:消极一点不去理他,反正不是error:-);积极一点,则想办法去掉。去掉又用两种方法:一种使用#pragma warning(disable: xxxx),眼不见,心不烦;另外就是找出解决问题的办法了。
今天做dll库时,在struct中用到了stl:
class CLASS_TEST
{
    …
private:
    std::vector<MY_STRUCT> m_structs;
}
但 是编译时,vs2005给出了warning C4251: ‘CLASS_TEST::m_structs’ : class ‘std::vector<_Ty>’ needs to have dll-interface to be used by clients of class ‘CLASS_TEST’的警告信息。费了很大的劲才解决掉,记录下来。

在头文件中,定义宏
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif

现在,在变量m_structs前,添加:
template class MYDLL_API std::allocator<myStruct>;
template class MYDLL_API std::vector<myStruct, std::allocator<myStruct> >;
这样,即可以了。


另一篇:

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

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

若想不使用通过关闭警告的方式关闭警告, 那么就这样
1)对于用户自定义的模板
   template class DLLImportExportMacro SomeTemplate<int>;
   SomeTemplate<int> y;
2)对于STL的模板
     template class DLLImportExportMacro std::allocator<int>
     template class DLLImportExportMacro std::vector<int,
      std::allocator<int> >;
     vector<int> m_data;

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

在window10安装vs2013编译,调试程序 给出解释并修正方案 下面是vs2013出现以下错误代码 warning C4251: “VTTestManagerBS::m_vtTestMap”: classstd::map<std::string,VTTestManagerBS::VTTestItem *,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>”需要有 dll 接口由 class“VTTestManagerBS”的客户端使用 1> with 1> [ 1> _Kty=std::string 1> , _Ty=VTTestManagerBS::VTTestItem * 1> ] 1>d:\rxxq-project\server_src _2013\server\code\sourcecode\src\foundation\VTTest.h(122): warning C4251: “VTTestManagerBS::m_vtTestList”: classstd::vector<VTTestManagerBS::VTTestItem *,std::allocator<_Ty>>”需要有 dll 接口由 class“VTTestManagerBS”的客户端使用 1> with 1> [ 1> _Ty=VTTestManagerBS::VTTestItem * 1> ] 1>d:\rxxq-project\server_src _2013\server\code\sourcecode\src\foundation\VTTest.h(124): warning C4251: “VTTestManagerBS::m_reportString”: classstd::basic_string<char,std::char_traits<char>,std::allocator<char>>”需要有 dll 接口由 class“VTTestManagerBS”的客户端使用 1>d:\rxxq-project\server_src _2013\server\code\sourcecode\src\foundation\VTTest.h(132): warning C4251: “VTTestManagerBS::m_reportPath”: classstd::basic_string<char,std::char_traits<char>,std::allocator<char>>”需要有 dll 接口由 class“VTTestManagerBS”的客户端使用 1>d:\rxxq-project\server_src _2013\server\code\sourcecode\src\foundation\VTTest.h(159): warning C4251: “VTTestOP::m_testName”: classstd::basic_string<char,std::char_traits<char>,std::allocator<char>>”需要有 dll 接口由 class“VTTestOP”的客户端使用 程序原代码: #ifndef LOG_MGR_SINGLETON_H #define LOG_MGR_SINGLETON_H 1 //资源管理类 #include "../Memory/FreeList.h" #include "../TObjectPool.h" #include <memory> // 添加智能指针支持 class LogManagerImpl; // 前置声明 class LogStream; //!日志记录的条目信息结构体 struct _Foundation_Export_ LOG_ITEM { public: ////!操纵控制块 表的互斥变量 static Thread::RecMutex m_mutex; _Def_Pool_Factory_(LOG_ITEM); //!日志条目配置信息 enum ENLOGITEMCONFIG { //!最大日志长度 enMaxLogItemSize = 1024, //!最大名字长度 enMaxLogNameSize = 32, }; char m_typeName[enMaxLogNameSize+1]; char m_szDesc[enMaxLogItemSize+1]; unsigned int m_nNumber; public: //结构体赋值 int SetValue(const std::string& strType, const char* pszDesc, const unsigned int nNumber) { size_t cpySize = enMaxLogNameSize > strType.size() ? strType.size() : enMaxLogNameSize; memcpy(m_typeName,strType.c_str(),cpySize); m_typeName[cpySize] = 0; m_nNumber = sizeof(m_szDesc); if (m_nNumber > nNumber) { m_nNumber = nNumber; } memcpy(m_szDesc, pszDesc, m_nNumber); return true; }; LOG_ITEM& operator = (const LOG_ITEM& item) { memcpy(m_typeName,item.m_typeName,sizeof(m_typeName)); m_nNumber = sizeof(item.m_szDesc); if (m_nNumber > item.m_nNumber) { m_nNumber = item.m_nNumber; } memcpy(m_szDesc, item.m_szDesc, m_nNumber); return *this; } LOG_ITEM& operator = (const LOG_ITEM* pItem) { memcpy(m_typeName,pItem->m_typeName,sizeof(m_typeName)); m_nNumber = pItem->m_nNumber; memcpy(m_szDesc, pItem->m_szDesc, m_nNumber); return *this; } void Reset(void) { } }; /** * @brief Log性能参数记录 */ class _Foundation_Export_ LogPerfData { public: LogPerfData(void) :m_logTotalCount(0) { } //!总共记录的条目数量 unsigned int m_logTotalCount; protected: private: }; /** *日志记录,单件模式 */ class _Foundation_Export_ LogMgrSingleton { _Singleton_Decl(LogMgrSingleton); public: // Constructor LogMgrSingleton(); // Destructor virtual ~LogMgrSingleton(); //!性能参数记录 LogPerfData m_perf; //日志有关操作 public: //!注册一个日志类型 bool RegisterLog(std::string strType); //!获得LogItem,以便于外部直接改写Item中的数据,避免一次拷贝 LOG_ITEM* GetLogItem(void); //!直接报告LogItem int Report(LOG_ITEM* item); //!日志输出,放入列表 int Report(const std::string& strType, const char* pszDesc, const int lNumber); //!日志输出, int ReportEx(const std::string& strType, char* pszDesc, int lNumber); //!线程调用的函数 static void WriteLog(void* ptr); //!具体的处理Log的函数 void WriteLogEx(); //!依据注册名,查找log流 LogStream* LookupStreamByName(const std::string& name); //输出流有关操作 public: //!压入一个stream,以后创建流就用这个创建 void PushStream(LogStream* stream); //!获得一个预先压入的stream LogStream* CreateStream(const std::string& n); //!弹出一个stream LogStream* PopStream(void); //创建文件有关操作 private: //!创建logs文件夹 int CreateLogsDirectory(void* pContext); //!创建当前日期文件夹 int CreateDateDirectory(void* pContext); //!获得当前日期 int GetCurrentDate(char* pszReturn, const int nLength); //!文件是否存在 int IsFileExist(std::string& strPath); private: //!从日志队列m_queLogList中获得第一个Log. LOG_ITEM* GetFrontLogData(void); private: //存放日志文件的句柄 std::map<std::string, FILE*> m_vecLogFileHandle; std::map<std::string, LogStream*> m_vecLogStream; //std::unique_ptr<LogManagerImpl> pImpl; // Pimpl惯用法 //File Handle FILE* m_hFile; //logs文件夹 std::string m_strLogsPath; std::stack<LogStream*> _streamStack; AG_Time m_AG_Time; private: Thread::BaseThread* m_LogThread; ////!操纵控制块 表的互斥变量 Thread::RecMutex m_mutex; //!开始log的信号量 Thread::Semaphore m_sem; private: //!日志结构体 LOG_ITEM m_LogItem; //!存放所有日志的线性链表(目前使用queue代替) std::queue<LOG_ITEM*> m_queLogList; //!下面创建的内存对象,最好能放到 private: //!创建玩家对象 LOG_ITEM* CreateLogItem(void); //!删除玩家对象 void FreeLogItem(LOG_ITEM* pLogItem); private: //预存放日志的内存分配 gems::FreeList< LOG_ITEM, gems::CompactableChunkPolicy<LOG_ITEM>, gems::ConstantChunkSizeGrowthPolicy<LOG_ITEM, 1024> > m_logMemoryList; }; //! #define LOG_REPORT_PUSHSTREAM(ptr) LogMgrSingleton::Instance()->PushStream(ptr) #define LOG_REPORT_POPSTREAM() LogMgrSingleton::Instance()->PopStream() //! #define LOG_REPORT_REGISTER(path) LogMgrSingleton::Instance()->RegisterLog(path) #define LOG_REPORT_EX(path, desc, num) LogMgrSingleton::Instance()->Report(path, desc, num) #define LOG_REPORT_LOOKUP(name) LogMgrSingleton::Instance()->LookupStreamByName(name) extern "C" { void _Foundation_Export_ _LOG_REPORT_OUTPUT_(const char* pszType,const char* pszString,...); #define LOG_REPORT_OUTPUT void _Foundation_Export_ _Server_LOG_File_(const char* pszType,const char* pszString,...); void _Foundation_Export_ debugOutputString(const char* pszString,...); //void _Foundation_Export_ LOG_REPORT_OUTPUT2( ); } #endif
最新发布
11-08
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值