衆所周知,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")
參考連接: