众所周知,printf是一个方便、直观、易写、变长参数的打印函数,但它有一个致命的缺陷,以下的语句将致使程序出现严重的运行时错误:html
printf("%s", 1);
而后程序中断,程序员深夜被电话叫醒……噩梦被打断之后陷入另外一个噩梦。深究之后发现,幕后黑手是C语言变长参数的传递问题。git
没有传递参数类型。程序员
没有传递参数个数。github
固然,在C语言里边仍是能够解决这个问题滴,但……却无可避免地失去了printf的优雅。C++改善了吗?失望……编程
直到C++终于释出了新的变元参数传递的标准。由Kenny Kerr(1)和sasha(2) 提出了设想。在github中,找到了一个解决方案 tinyformat(3)。json
但事情尚未结束,要把tinyformat用于log4cpp中,为使用vc2010编程的项目提供一个的安全可靠的日志模块。尤为是对于服务程序来讲,日用不能停。安全
log4cpp有一大堆配置语句,使用起来不是很方便,参照Lan'Sir(4)的文章进行以下封装:多线程
class LogBase { private: static LogBase *m_pInstance; log4cpp::Category *m_pRoot; protected: LogBase() { m_pRoot = &log4cpp::Category::getRoot(); m_pRoot->setPriority(log4cpp::Priority::INFO); } private: LogBase& operator=(LogBase&); LogBase(const LogBase&); public: ~LogBase() { if ( m_pRoot != NULL) { delete m_pRoot; m_pRoot = NULL; } if ( m_pInstance != NULL) { delete m_pInstance; m_pInstance = NULL; } } static LogBase* getInstance() { if( m_pInstance == NULL) m_pInstance = new LogBase(); return m_pInstance; } void log(log4cpp::Priority::Value priority, const std::string& message) { if (m_pRoot != NULL) m_pRoot->log(priority, message); } }; LogBase* LogBase::m_pInstance = NULL;
使人郁闷的是vs2010支持C++98而不是C++11。幸亏tinyformat做者已经作了一些工做——用宏定义循环设置了1-16个变元的函数。函数
// C++98 version void log_info(const char* s) { std::string m = s; LogBase *pInstance = LogBase::getInstance(); \ if (pInstance != NULL) pInstance->log(log4cpp::Priority::INFO, s); \ } #define MAKE_LOG_INFO_FUNC(n) \ template<TINYFORMAT_ARGTYPES(n)> \ void log_info(const char* fmt, TINYFORMAT_VARARGS(n)) \ { \ std::string m = tfm::format(fmt, TINYFORMAT_PASSARGS(n)); \ LogBase *pInstance = LogBase::getInstance(); \ if (pInstance != NULL) pInstance->log(log4cpp::Priority::INFO, m); \ } TINYFORMAT_FOREACH_ARGNUM(MAKE_LOG_INFO_FUNC)
如今就能够试一试了:.net
int _tmain(int argc, _TCHAR* argv[]) { log_info("hello %s!", 555); log_info("hello world%s!"); return 0; }
在本身的项目中同时使用jsoncpp和log4cpp的lib
分别编译lib时,需将属性.C/C++.代码生成.运行库
统一。例如都设置为“多线程/MT”或者都设置为“多线程调试/MTD”。
在不一样类型的运行库中存在一样的一些函数名,链接在一块儿时将出现重复定义和定义冲突错误。
具体内容可参考文章:“关于VC link2005 重复定义,定义冲突的错误解决”(5)以及“配置本身的OpenGL库,glew、freeglut库编译,库冲突解决(附OpenGL Demo程序)”(6)
消除警告:未找到 PDB“vc100.pdb”
编译jsoncpp和log4cpp的lib时,部分调试信息被放在 vc100.pdb 文件中。编译连接本身的项目时出现找不到 vc100.pdb 的告警信息。
通常状况下,在调试本身的项目时都不会跟踪到jsoncpp和log4cpp的内部。若是真的怀疑它们有问题,也是到它们各自的项目中进行调试。所以,简单合理的解决办法是在编译lib时,关闭调试信息。
将属性.C/C++.常规.调试信息格式
设置为空。
若是在本身的项目中仍然但愿保留lib的这些调试信息,要解决文件名冲突的问题。详见“warning LNK4099: 未找到 PDB”(7)
消除警告:没法解析的外部符号 __imp__WSACleanup
编译log4cpp的lib时可能会用到ws2_32.lib。详见“没法解析的外部符号 __imp__WSACleanup@”(8)。
在添加头文件处,添加引用:
#pragma comment(lib,"ws2_32.lib")
参考连接: