亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

基于Windows C++ 應(yīng)用程序通用日志組件的使用詳解

 更新時(shí)間:2013年05月08日 10:37:02   作者:  
眾所周知,在調(diào)試、跟蹤和執(zhí)行應(yīng)用程序的過(guò)程中,程序的日志能為這些工作提供大量有價(jià)值的運(yùn)行信息。因此,程序的日志對(duì)應(yīng)用程序的運(yùn)行、維護(hù)至關(guān)重要

引言

  在如何記錄程序日志方面,通常有三種選擇:

  1、采用Log4CXX等公共開(kāi)源日志組件:這類日志組件的特點(diǎn)是跨平臺(tái)且功能比較強(qiáng)大,例如可以把日志發(fā)往另一臺(tái)服務(wù)器或記錄到數(shù)據(jù)庫(kù)中等;另外,可配置性較高,可以通過(guò)配置文件或程序代碼對(duì)日志進(jìn)行很多個(gè)性化設(shè)置。但從另外一個(gè)角度看,由于這些優(yōu)點(diǎn)往往也導(dǎo)致了在使用方面的缺點(diǎn)。首先,對(duì)于一般應(yīng)用程序來(lái)說(shuō),它們并不需要太多的功能,通常只需要把日志記錄到文件或反饋到應(yīng)用程序,功能太多反正讓用戶使用起來(lái)覺(jué)得繁瑣還得背負(fù)很多從來(lái)都用不到的代碼。其次,這類日志組件通常是跨平臺(tái)的,并不只是針對(duì) Windows 或 VC 的應(yīng)用程序,因此使用起來(lái)總會(huì)覺(jué)得有點(diǎn)別扭,例如他們的字符都是用 char 類型的,對(duì)于一個(gè) Unicode 程序來(lái)說(shuō)每次寫(xiě)日志都要做字符轉(zhuǎn)換是很不爽的事情,本座在多年前曾經(jīng)使用過(guò) Log4Cpp ,程序執(zhí)行時(shí)總是報(bào)告日志組件有內(nèi)存泄露,雖然有可能是誤報(bào),但是使用起來(lái)總覺(jué)得很不舒服。

  2、自己寫(xiě)幾個(gè)簡(jiǎn)單的類或函數(shù)記錄日志:這種方法的確很簡(jiǎn)單,通常都不用一兩百行的代碼。但這種方法通常缺乏規(guī)范性和通用性,其他程序需要記錄類似的但有點(diǎn)差異的日志時(shí),通常的作法是:Copy-Paste-Modify;另外,這類方法很可能也沒(méi)有考慮性能或并發(fā)方面的問(wèn)題,通常是直接在工作線程中寫(xiě)日志,對(duì)于那些性能要求較高的應(yīng)用程序是絕對(duì)不允許的。

  3、干脆不記錄任何日志:的確,現(xiàn)在很多程序由于各種原因并沒(méi)有記錄任何日志。但本座以為,如果一個(gè)程序是有用的,具備一定功能,并且需要連續(xù)運(yùn)行較長(zhǎng)一段時(shí)間,那么記錄日志是必須的;否則,得認(rèn)真考慮該程序是否有存在的必要了。
 

設(shè)計(jì)

  綜上所述,編寫(xiě)一個(gè)通用的日志組件應(yīng)該著重考慮三個(gè)方面:功能、可用性和性能。下面,本座詳細(xì)說(shuō)明在設(shè)計(jì)日志組件時(shí)對(duì)這些方面問(wèn)題的考慮:

  1、功能:本日志組件的目的是滿足大多數(shù)應(yīng)用程序記錄日志的需求 —— 把日志輸出到文件或發(fā)送到應(yīng)用程序中,并不提供一些復(fù)雜但不常用的功能。本日志組件的功能包括:

    把日志信息輸出到指定文件

    每日生成一個(gè)日志文件

    對(duì)于 GUI 程序,可以把日志信息發(fā)送到指定窗口

    對(duì)于Console應(yīng)用程序,可以把日志信息發(fā)往標(biāo)準(zhǔn)輸出 (std::cout)

    支持 MBCS / UNICODE,Console / GUI 程序

    支持動(dòng)態(tài)加載和靜態(tài)加載日志組件 DLL

    支持 DEBUG/TRACE/INFO/WARN/ERROR/FATAL 等多個(gè)日志級(jí)別

  2、可用性:本日志組件著重考慮了可用性,盡量讓使用者用起來(lái)覺(jué)得簡(jiǎn)便、舒心:

    簡(jiǎn)單純凈:不依賴任何程序庫(kù)或框架

    使用接口簡(jiǎn)單,不需復(fù)雜的配置或設(shè)置工作

    提供 CStaticLogger 和 CDynamicLogger 包裝類用于靜態(tài)或動(dòng)態(tài)加載以及操作日志組件,用戶無(wú)需關(guān)注加載細(xì)節(jié)

    程序如果要記錄多個(gè)日志文件只需為每個(gè)日志文件創(chuàng)建相應(yīng)的 CStaticLogger 或 CDynamicLogger 對(duì)象

    只需調(diào)用 Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法記錄日志

    日志記錄方法支持可變參數(shù)

    日志輸出格式:<時(shí)間> <線程ID> <日志級(jí)別> <日志內(nèi)容>

  3、性能:性能是組件是否值得使用的硬指標(biāo),本組件從設(shè)計(jì)到編碼的過(guò)程都盡量考慮到性能優(yōu)化:

    支持多線程同時(shí)發(fā)送寫(xiě)日志請(qǐng)求

    使用單獨(dú)線程在后臺(tái)寫(xiě)日志,不影響工作線程的正常執(zhí)行

    采用批處理方式批量記錄日志






接口

  1、ILogger:日志組件對(duì)象接口

復(fù)制代碼 代碼如下:

/******************************************************************************
 Module:  Logger.h
 Notices: Copyright (c) 2012 Bruce Liang - http://www.cnblogs.com/ldcsaa/

 Purpose: 記錄程序日志。
         1. 把日志信息輸出到指定文件
         2. 對(duì)于 GUI 程序,可以把日志信息發(fā)送到指定窗口
         3. 對(duì)于Console應(yīng)用程序,可以把日志信息發(fā)往標(biāo)準(zhǔn)輸出 (std::cout)

 Desc:
         1、功能:
         --------------------------------------------------------------------------------------
         a) 把日志信息輸出到指定文件
         b) 每日生成一個(gè)日志文件
         c) 對(duì)于 GUI 程序,可以把日志信息發(fā)送到指定窗口
         d) 對(duì)于Console應(yīng)用程序,可以把日志信息發(fā)往標(biāo)準(zhǔn)輸出 (std::cout)
         e) 支持 MBCS / UNICODE,Console / GUI 程序
         f) 支持動(dòng)態(tài)加載和靜態(tài)加載日志組件 DLL
         g) 支持 DEBUG/TRACE/INFO/WARN/ERROR/FATAL 等多個(gè)日志級(jí)別

         2、可用性:
         --------------------------------------------------------------------------------------
         a) 簡(jiǎn)單純凈:不依賴任何程序庫(kù)或框架
         b) 使用接口簡(jiǎn)單,不需復(fù)雜的配置或設(shè)置工作
         c) 提供 CStaticLogger 和 CDynamicLogger 包裝類用于靜態(tài)或動(dòng)態(tài)加載以及操作日志組件,用戶無(wú)需關(guān)注加載細(xì)節(jié)
         d) 程序如果要記錄多個(gè)日志文件只需為每個(gè)日志文件創(chuàng)建相應(yīng)的 CStaticLogger 或 CDynamicLogger 對(duì)象
         e) 只需調(diào)用 Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法記錄日志
         f) 日志記錄方法支持可變參數(shù)
         g) 日志輸出格式:<時(shí)間> <線程ID> <日志級(jí)別> <日志內(nèi)容>

         3、性能:
         --------------------------------------------------------------------------------------
         a) 支持多線程同時(shí)發(fā)送寫(xiě)日志請(qǐng)求
         b) 使用單獨(dú)線程在后臺(tái)寫(xiě)日志,不影響工作線程的正常執(zhí)行
         c) 采用批處理方式批量記錄日志

 Usage:
         方法一:(靜態(tài)加載 Logger DLL)
         --------------------------------------------------------------------------------------
         0. 應(yīng)用程序包含 StaticLogger.h 頭文件
         1. 創(chuàng)建 CStaticLogger 對(duì)象(通常為全局對(duì)象)
         2. 調(diào)用 CStaticLogger->Init(...) 初始化日志組件
         3. 使用 CStaticLogger->Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法寫(xiě)日志
         4. 調(diào)用 CStaticLogger->UnInit(...) 清理日志組件(CStaticLogger 對(duì)象析構(gòu)時(shí)也會(huì)自動(dòng)清理日志組件)

         方法二:(動(dòng)態(tài)加載 Logger DLL)
         --------------------------------------------------------------------------------------
         0. 應(yīng)用程序包含 DynamicLogger.h 頭文件
         1. 創(chuàng)建 CDynamicLogger 對(duì)象(通常為全局對(duì)象)
         2. 調(diào)用 CDynamicLogger->Init(...) 初始化日志組件
         3. 使用 CDynamicLogger->Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法寫(xiě)日志
         4. 調(diào)用 CDynamicLogger->UnInit(...) 清理日志組件(CDynamicLogger 對(duì)象析構(gòu)時(shí)也會(huì)自動(dòng)清理日志組件)

         方法三:(直接用導(dǎo)出函數(shù)加載 Logger DLL)
         --------------------------------------------------------------------------------------
         0. 應(yīng)用程序包含 Logger.h 頭文件
         1. 手工調(diào)用 ILoger_Create() 和 ILoger_Create() 導(dǎo)出函數(shù)創(chuàng)建和銷毀 ILogger 對(duì)象
         (注:如果是動(dòng)態(tài)加載,需手工調(diào)用 ::LoadLibrary()/::FreeLibrary() 系列 API 函數(shù)加載和卸載 Logger DLL)

         [
             ***** 對(duì)于希望通過(guò)窗口接收日志信息的 GUI 程序 *****

             A. 日志組件初始化成功后調(diào)用 SetGUIWindow(HWND) 設(shè)置收日志的窗口
             B. 窗口須響應(yīng)處理 LOG_MESSAGE 消息
             C. 處理完 LOG_MESSAGE 消息后,調(diào)用 ILogger::FreeLogMsg() 銷毀接收到的 TLogMsg
         ]

 Environment:
         1. Windows 2000 or later (_WIN32_WINNT >= 0x0500)
         2. VC++ 2010 or later

 Release:
         1. Logger_C.dll     - Console/MBCS/Release
         2. Logger_CD.dll    - Console/MBCS/Debug
         3. Logger_CU.dll    - Console/Unicode/Release
         4. Logger_CUD.dll   - Console/Unicode/Debug
         5. Logger.dll       - GUI/MBCS/Release
         6. Logger_D.dll     - GUI/MBCS/Debug
         7. Logger_U.dll     - GUI/Unicode/Release
         8. Logger_UD.dll    - GUI/Unicode/Debug

 Examples:
         1. TestGUILogger        - GUI 版測(cè)試程序       (靜態(tài)加載)
         2. TestDynamicLogger    - GUI 版測(cè)試程序       (動(dòng)態(tài)加載)
         3. TestConsoleLogger    - Console 版測(cè)試程序  (靜態(tài)加載)

 ******************************************************************************/

 #pragma once

 /**************************************************/
 /********** imports / exports Logger.dll **********/

 #ifdef LOGGER_EXPORTS
     #define LOGGER_API __declspec(dllexport)
     //#define TRY_INLINE    inline
 #else
     #define LOGGER_API __declspec(dllimport)
     //#define TRY_INLINE
 #endif

 /**************************************************/
 /****************** 日志組件接口 *******************/

 class LOGGER_API ILogger
 {
 public:
     /***** 日志級(jí)別 *****/
     enum LogLevel
     {
         LL_NONE     = 0XFF,
         LL_DEBUG    = 1,
         LL_TRACE    = 2,
         LL_INFO     = 3,
         LL_WARN     = 4,
         LL_ERROR    = 5,
         LL_FATAL    = 6
     };

     /***** 操作錯(cuò)誤碼 *****/
     enum ErrorCode
     {
         // 無(wú)錯(cuò)誤
         EC_OK    = NO_ERROR,
         // 文件操作相關(guān)的錯(cuò)誤
         EC_FILE_GENERIC,
         EC_FILE_FILENOTFOUND,
         EC_FILE_BADPATH,
         EC_FILE_TOMANYOPERFILES,
         EC_FILE_ACCESSDENIED,
         EC_FILE_INVALIDFILE,
         EC_FILE_REMOVECURRENTDIR,
         EC_FILE_DIRECTORYFULL,
         EC_FILE_BADSEEK,
         EC_FILE_HARDIO,
         EC_FILE_SHARINGVIOLATION,
         EC_FILE_LOCKVIOLATION,
         EC_FILE_DISKFULL,
         EC_FILE_ENDOFFILE,
         // 其他錯(cuò)誤
         EC_INVALID_STATE,
         EC_INIT_LOGLEVEL,
         EC_INIT_PRINTFLAG,
         EC_INIT_CREATE_LOG_THREAD_FAIL
     };

     /******************************************
                     日志信息結(jié)構(gòu)
     *******************************************/
     struct TLogMsg
     {
         DWORD       m_dwSize;       // 結(jié)構(gòu)大小 - 跟據(jù)消息長(zhǎng)度動(dòng)態(tài)變化
         LogLevel    m_logLevel;     // 日志級(jí)別
         UINT        m_uiThreadID;   // 線程ID
         SYSTEMTIME  m_stMsgTime;    // 記錄時(shí)間
         TCHAR       m_psMsg[1];     // 消息內(nèi)容
     };

 public:
     ILogger(void);
     virtual ~ILogger(void);
 private:
     ILogger(const ILogger&);
     ILogger& operator = (const ILogger&);

 public:
     // 日志組件初始化方法
     virtual BOOL Init(
                         LPCTSTR logFile  = NULL                  // 日志文件. 默認(rèn): {AppPath}/logs/{AppName}-YYYYMMDD.log
                       , LogLevel ll      = DEFAULT_LOG_LEVEL     // 日志級(jí)別. 默認(rèn): [Debug -> LL_DEBUG] / [Release -> LL_INFO]
                       , int printFlag    = DEFAULT_PRINT_FLAG    // 輸出掩碼. 是否輸出到文件和(或)屏幕. 默認(rèn): 只輸出到文件
                      )       = 0;
     // 日志組件清理方法
     virtual BOOL UnInit()    = 0;

 public:
     // 寫(xiě)日志方法:傳入日志內(nèi)容字符串(對(duì)于不需要格式化的日志文本,用本方法效率最高)
     virtual void Log_0  (LogLevel ll, LPCTSTR msg) = 0;
     virtual void Debug_0(LPCTSTR msg);
     virtual void Trace_0(LPCTSTR msg);
     virtual void Info_0 (LPCTSTR msg);
     virtual void Warn_0 (LPCTSTR msg);
     virtual void Error_0(LPCTSTR msg);
     virtual void Fatal_0(LPCTSTR msg);

     // 寫(xiě)日志方法:傳入格式化字符串和參數(shù)棧指針(通常只在組件內(nèi)部使用)
     virtual void LogV   (LogLevel ll, LPCTSTR format, va_list arg_ptr);

     // 寫(xiě)日志方法:傳入格式化字符串和可變參數(shù)(非常靈活簡(jiǎn)便)
     virtual void Log     (LogLevel ll, LPCTSTR format, ...);
     virtual void Debug   (LPCTSTR format, ...);
     virtual void Trace   (LPCTSTR format, ...);
     virtual void Info    (LPCTSTR format, ...);
     virtual void Warn    (LPCTSTR format, ...);
     virtual void Error   (LPCTSTR format, ...);
     virtual void Fatal   (LPCTSTR format, ...);

     // 寫(xiě)日志方法:傳入格式化字符串和可變參數(shù)(與上一組方法類似,但在進(jìn)行任何操作前會(huì)檢查日志級(jí)別)
     virtual void TryLog     (LogLevel ll, LPCTSTR format, ...);
     virtual void TryDebug   (LPCTSTR format, ...);
     virtual void TryTrace   (LPCTSTR format, ...);
     virtual void TryInfo    (LPCTSTR format, ...);
     virtual void TryWarn    (LPCTSTR format, ...);
     virtual void TryError   (LPCTSTR format, ...);
     virtual void TryFatal   (LPCTSTR format, ...);

     // 通用輔助方法
     virtual BOOL HasInited           ()        const    = 0;        // 是否已經(jīng)初始化                           
     virtual BOOL IsPrint2File        ()        const    = 0;        // 是否把日志輸出到文件   
     virtual BOOL IsPrint2Screen      ()        const    = 0;        // 是否把日志輸出到屏幕窗口   
     virtual int    GetPrintFlag      ()        const    = 0;        // 打印標(biāo)志                   
     virtual LogLevel    GetLogLevel  ()        const    = 0;        // 日志級(jí)別       
     virtual LPCTSTR        GetLogFile()        const    = 0;        // 日志文件
     virtual ErrorCode    GetLastError()        const    = 0;        // 當(dāng)前操作錯(cuò)誤碼

 /****************************** GUI ******************************/
 #ifdef _WINDOWS
     public:
         // 設(shè)置接收日志信息的窗口, hWndGUI == NULL 則取消接收
         virtual void SetGUIWindow(HWND hWndGUI)    = 0;
         // 獲取接收日志信息的窗口
         virtual HWND GetGUIWindow()                = 0;

         // 銷毀在發(fā)送 LOG_MESSAGE 消息時(shí)動(dòng)態(tài)創(chuàng)建的 TLogMsg 對(duì)象
         virtual void FreeLogMsg(const TLogMsg* pLogMsg);

         // 虛擬窗口句柄標(biāo)掩碼:用于向 GUI 窗口發(fā)送 LOG_MESSAGE 消息時(shí)作為發(fā)送源標(biāo)識(shí)
         static const int LOGGER_FAKE_WINDOW_BASE = 0X80001111;
         // 自定義日志消息:通過(guò)本消息向 GUI 窗口發(fā)送日志
         // 其中:WPARAM -> ILogger 對(duì)象指針,LPARAM -> TLogMsg 結(jié)構(gòu)體指針
         static const int LOG_MESSAGE = WM_USER | (0x7FFF & LOGGER_FAKE_WINDOW_BASE);
 #endif

 public:
     static const int PRINT_FLAG_FILE            = 0x00000001;            // 打印到文件
     static const int PRINT_FLAG_SCREEN          = 0x00000002;            // 打印到屏幕
     static const int DEFAULT_PRINT_FLAG         = PRINT_FLAG_FILE;        // 默認(rèn)日志掩碼
     static const LogLevel DEFAULT_LOG_LEVEL     =
 #ifdef _DEBUG
                 LL_DEBUG
 #else
                 LL_INFO
 #endif

 };

 /**************************************************/
 /************** Logger DLL 導(dǎo)出函數(shù) ***************/

 // 創(chuàng)建 ILogger 對(duì)象
 EXTERN_C LOGGER_API ILogger* ILogger_Create();
 // 銷毀 ILogger 對(duì)象
 EXTERN_C LOGGER_API void ILogger_Destroy(ILogger* p);

 // 獲取各日志級(jí)別的文字描述
 EXTERN_C LOGGER_API LPCTSTR    ILogger_GetLogLevelDesc (ILogger::LogLevel ll);
 // 獲取各操作錯(cuò)誤碼的文字描述
 EXTERN_C LOGGER_API LPCTSTR    ILogger_GetErrorDesc    (ILogger::ErrorCode ec);

 

   代碼中的注釋基本已經(jīng)能夠說(shuō)明日志組件的使用方法,這里只做一些簡(jiǎn)單的概括:

  版本:日志組件以 DLL 的形式提供,已編譯成 Debug/Release、MBCS/Unicode、GUI/Console 8個(gè)版本

  測(cè)試:三個(gè)測(cè)試程序 TestGUILogger、TestDynamicLogger 和 TestConsoleLogger 用于測(cè)試所有版本。其中 TestDynamicLogger 采用動(dòng)態(tài)加載方式加載 Logger DLL

  使用方法:

    0. 應(yīng)用程序包含 Logger.h 頭文件
    1. 調(diào)用 ILogger_Create() 導(dǎo)出函數(shù)創(chuàng)建 ILogger 對(duì)象
    2. 調(diào)用 ILogger->Init(...) 初始化日志組件
    3. 使用 ILogger->Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法寫(xiě)日志
    4. 調(diào)用 ILogger->UnInit(...) 清理日志組件
    5. 調(diào)用 ILogger_Destroy() 導(dǎo)出函數(shù)銷毀 ILogger 對(duì)象
 

  2、CStaticLogger:ILogger 包裝器(智能指針)—— 用于靜態(tài)加載 Logger DLL

復(fù)制代碼 代碼如下:

#pragma once

 #include "Logger.h"

 /**************************************************/
 /********* http://www.cnblogs.com/ldcsaa/ *********/
 /********** ILogger 包裝器(智能指針) ***********/
 /*********** 用于靜態(tài)加載 Logger DLL ************/

 class LOGGER_API CStaticLogger
 {
 public:
     // 構(gòu)造函數(shù):如果 bCreate 為 TRUE,則在構(gòu)建 CStaticLogger 實(shí)例的同時(shí)創(chuàng)建 ILogger 對(duì)象
     CStaticLogger(BOOL bCreate = TRUE);
     // 析構(gòu)函數(shù)
     ~CStaticLogger();
 private:
     CStaticLogger(const CStaticLogger&);
     CStaticLogger& operator = (const CStaticLogger&);

 public:
     inline void Reset           (ILogger* pLogger);     // 重設(shè)其封裝的 ILogger 指針
     inline BOOL IsValid         ()    const;            // 判斷其封裝的 ILogger 指針是否非空
     inline ILogger* Get         ()    const;            // 獲取 ILogger 指針
     inline ILogger& operator *  ()    const;            // 獲取 ILogger 引用
     inline ILogger* operator -> ()    const;            // 獲取 ILogger 指針
     inline operator ILogger*    ()    const;            // 轉(zhuǎn)換為 ILogger 指針

 private:
     ILogger* m_pLogger;
 };

  CStaticLogger 為簡(jiǎn)化日志組件使用而設(shè)計(jì),用于靜態(tài)加載 Logger DLL 的場(chǎng)合。使用方法:

    0. 應(yīng)用程序包含 StaticLogger.h 頭文件
    1. 創(chuàng)建 CStaticLogger 對(duì)象(通常為全局對(duì)象)
    2. 調(diào)用 CStaticLogger->Init(...) 初始化日志組件
    3. 使用 CStaticLogger->Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法寫(xiě)日志
    4. 調(diào)用 CStaticLogger->UnInit(...) 清理日志組件(CStaticLogger 對(duì)象析構(gòu)時(shí)也會(huì)自動(dòng)清理日志組件)

 

  3、CDynamicLogger:ILogger 包裝器(智能指針)—— 用于動(dòng)態(tài)加載 Logger DLL

復(fù)制代碼 代碼如下:

#pragma once

 #include "Logger.h"

 /**************************************************/
 /********* http://www.cnblogs.com/ldcsaa/ *********/
 /************** Logger DLL 默認(rèn)文件名 ***************/

 #ifdef _DEBUG
     #ifdef _UNICODE
         #ifdef _WINDOWS
             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger_UD.dll")
         #else
             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger_CUD.dll")
         #endif
     #else
         #ifdef _WINDOWS
             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger_D.dll")
         #else
             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger_CD.dll")
         #endif
     #endif
 #else
     #ifdef _UNICODE
         #ifdef _WINDOWS
         #define DEF_LOGGER_DLL_FILE_PATH        _T("Logger_U.dll")
         #else
             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger_CU.dll")
         #endif
     #else
         #ifdef _WINDOWS
             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger.dll")
         #else
             #define DEF_LOGGER_DLL_FILE_PATH    _T("Logger_C.dll")
         #endif
     #endif
 #endif

 /**************************************************/
 /*************** Logger DLL 導(dǎo)出函數(shù) ***************/

 // 創(chuàng)建 ILogger 對(duì)象
 typedef ILogger*            (*FN_ILogger_Create)            ();
 // 銷毀 ILogger 對(duì)象
 typedef void                (*FN_ILogger_Destroy)           (ILogger* p);
 // 獲取各日志級(jí)別的文字描述
 typedef LPCTSTR             (*FN_ILogger_GetLogLevelDesc)   (ILogger::LogLevel ll);
 // 獲取各操作錯(cuò)誤碼的文字描述
 typedef LPCTSTR             (*FN_ILogger_GetErrorDesc)      (ILogger::ErrorCode ec);

 /*************************************************/
 /********** ILogger 包裝器(智能指針) ***********/
 /************ 用于動(dòng)態(tài)加載 Logger DLL ************/

 class CDynamicLogger
 {
 public:
     // 構(gòu)造函數(shù):如果 bLoad 為 TRUE,則在構(gòu)建 CDynamicLogger 示例的同時(shí)創(chuàng)建 ILogger 對(duì)象
     CDynamicLogger(BOOL bLoad = TRUE, LPCTSTR lpszFilePath = DEF_LOGGER_DLL_FILE_PATH)
     {
         Reset();

         if(bLoad)
             Load(lpszFilePath);
     }

     // 析構(gòu)函數(shù)
     ~CDynamicLogger()
     {
         Free();
     }

 private:
     CDynamicLogger(const CDynamicLogger&);
     CDynamicLogger& operator = (const CDynamicLogger&);

 public:
     // 創(chuàng)建 ILogger 對(duì)象
     ILogger* ILogger_Create()
         {return m_fnILoggerCreate();}
     // 銷毀 ILogger 對(duì)象
     void ILogger_Destroy(ILogger* p)
         {m_fnILoggerDestroy(p);}
     // 獲取各日志級(jí)別的文字描述
     LPCTSTR    ILogger_GetLogLevelDesc(ILogger::LogLevel ll)
         {return m_fnILoggerGetLogLevelDesc(ll);}
     // 獲取各操作錯(cuò)誤碼的文字描述
     LPCTSTR    ILogger_GetErrorDesc(ILogger::ErrorCode ec)
         {return m_fnILoggerGetErrorDesc(ec);}

     // 加載 Logger DLL
     BOOL Load(LPCTSTR lpszFilePath = DEF_LOGGER_DLL_FILE_PATH)
     {
         if(IsValid())
             return FALSE;

         BOOL isOK = FALSE;
         m_hLogger = ::LoadLibrary(lpszFilePath);

         if(m_hLogger)
         {
             m_fnILoggerCreate            = (FN_ILogger_Create)            ::GetProcAddress(m_hLogger, "ILogger_Create");
             m_fnILoggerDestroy           = (FN_ILogger_Destroy)           ::GetProcAddress(m_hLogger, "ILogger_Destroy");
             m_fnILoggerGetLogLevelDesc   = (FN_ILogger_GetLogLevelDesc)   ::GetProcAddress(m_hLogger, "ILogger_GetLogLevelDesc");
             m_fnILoggerGetErrorDesc      = (FN_ILogger_GetErrorDesc)      ::GetProcAddress(m_hLogger, "ILogger_GetErrorDesc");

             if(m_fnILoggerCreate && m_fnILoggerDestroy)
             {
                 m_pLogger   = ILogger_Create();
                 isOK        = (m_pLogger != NULL);
             }
         }

         if(!isOK)
             Free();

         return isOK;
     }

     // 卸載 Logger DLL
     BOOL Free()
     {
         if(!IsValid())
             return TRUE;

         BOOL isOK = TRUE;

         if(m_pLogger)    ILogger_Destroy(m_pLogger);
         if(m_hLogger)    isOK = ::FreeLibrary(m_hLogger);

         Reset();

         return isOK;
     }

     BOOL IsValid            ()    const    {return m_pLogger != NULL;}  // 判斷其封裝的 ILogger 指針是否非空
     ILogger* Get            ()    const    {return m_pLogger;}          // 獲取 ILogger 指針
     ILogger& operator *     ()    const    {return *m_pLogger;}         // 獲取 ILogger 引用
     ILogger* operator ->    ()    const    {return m_pLogger;}          // 獲取 ILogger 指針
     operator ILogger*       ()    const    {return m_pLogger;}          // 轉(zhuǎn)換為 ILogger 指針

 private:
     void Reset()
     {
         m_hLogger                    = NULL;
         m_pLogger                    = NULL;
         m_fnILoggerCreate            = NULL;
         m_fnILoggerDestroy           = NULL;
         m_fnILoggerGetLogLevelDesc   = NULL;
         m_fnILoggerGetErrorDesc      = NULL;
     }

 private:
     HMODULE         m_hLogger;
     ILogger*        m_pLogger;

     FN_ILogger_Create            m_fnILoggerCreate;
     FN_ILogger_Destroy           m_fnILoggerDestroy;
     FN_ILogger_GetLogLevelDesc   m_fnILoggerGetLogLevelDesc;
     FN_ILogger_GetErrorDesc      m_fnILoggerGetErrorDesc;
 };

 

  CDynamicLogger 為簡(jiǎn)化日志組件使用而設(shè)計(jì),用于動(dòng)態(tài)加載 Logger DLL 的場(chǎng)合。使用方法:

    0. 應(yīng)用程序包含 DynamicLogger.h 頭文件
    1. 創(chuàng)建 CDynamicLogger 對(duì)象(通常為全局對(duì)象)
    2. 調(diào)用 CDynamicLogger->Init(...) 初始化日志組件
    3. 使用 CDynamicLogger->Log()/Debug()/Trace()/Info()/Warn()/Error()/Fatal() 等方法寫(xiě)日志
    4. 調(diào)用 CDynamicLogger->UnInit(...) 清理日志組件(CDynamicLogger 對(duì)象析構(gòu)時(shí)也會(huì)自動(dòng)清理日志組件)

相關(guān)文章

最新評(píng)論