11

他のライブラリまたは実行可能ファイルで使用することを目的としたc++共有ライブラリを作成しています。ライブラリに一般的なログを追加するための最良の方法は何ですか?理想的には、ライブラリのユーザーが選択したログ機能にライブラリを適合させたいと思います。ライブラリにクラスがあるとします

class A {
  public: 
  void method(string param1, int param2);
}   

void A::method(string param1, int param2){
  /* i want to log values of param1 and param2, 
     but actual logging method must be defined outside of my library. 
     Maybe some kind of macro should help here. */ 
   /*e.g.*/  GENERICLOG_DEBUG("param1=" + param1+ " param2="+param1);
   /*if so, what that macro body should look like ? */
}

ライブラリをlog4XXX固有のAPIに関連付けたくありません。

4

6 に答える 6

14

ライブラリのユーザーがライブラリにアダプタをログに提供できるようにするコールバックメカニズムを提供できます。

つまり、ライブラリで抽象ロギングインターフェイスクラスを提供します。例:

class Logger
{
public:
    virtual ~Logger () {}
    virtual void log (const std::string& message) = 0;
};

ロガーを登録するクラス:

class Log
{
private:
    static Logger* logger_;
public:
    static void registerLogger (Logger& logger)
    { logger_ = &logger; }

    static void log (const std::string& message)
    { if (logger_ != 0) logger_->log (message); }
};

次に、ライブラリは次のようなログを記録します。

Log::log ("My log message");

ライブラリを使用するアプリケーションは、Logger(つまり、具体的なサブクラス)の実装を提供し、それをLogクラスに登録する必要があります。彼らのLoggerimplは、適切と思われるロギングを実装します。

これにより、さまざまなログライブラリを使用するアプリケーションでライブラリを使用できるようになります。

上記のコードは基本的なものであり、テストされていないことに注意してください。実際には、ログ方法を変更して、ログレベルパラメータなどを含めることができます。

于 2009-07-16T11:35:18.857 に答える
2

ライブラリでロギング関数のプロトタイプを宣言します。

extern void __cdecl UserLog(char* stText);

ライブラリに実装しないでください。ライブラリのユーザーはこの関数を実装する必要があり、ライブラリはユーザーの実装を使用します。

ユーザーの実装は次のようになります(これは単なるサンプルです)。

void __cdecl UserLog(char* stText)
{
  std::cout << stText << std::endl;
}

これは、ライブラリが静的ライブラリである場合に有効です。

コードでは、次のように使用できます。

class A {
  public: 
  void method(string param1, int param2);
}   

void A::method(string param1, int param2){
   string formatted = str( boost::format( "param1=%s param2=%d" ) % param1 % param2 );
   UserLog( formatted.c_str() );
}
于 2009-07-16T10:22:43.043 に答える
1

log4cxxまたはlog4cplusを使用します。

于 2009-07-16T09:10:33.110 に答える
0

既存のロギングライブラリを使用したくない場合は、マクロの使用を試みることができます。独自のlibを提供し、フォーマットメカニズムのようなprintfを備えたマクロで使用できるようにすることをお勧めします。

私は過去にそのようなことをしました。プラグインを介して拡張できる実際のロギングをカプセル化するログオブジェクトと呼ばれるマクロ。

しかし、私はLog4xxxによって同様のことがすでに行われていると思うので、それを見るのは良いことかもしれません。

ここに提案があります(テストする時間がありません、うまくいくことを願っています)

ヘッダ:

#ifdef _MYAPI_IMPL
#define MY_API __declspec(dllexport)
#そうしないと
#define MY_API __declspec(dllimport)
#endif

クラスMY_APIログ
{{
公衆:
    列挙型レベル{エラー、警告、情報、デバッグ};
    Log(レベルレベル、const char *ファイル、int行);
    void operator()(const char * Format、...);
プライベート:
       const char * m_file;
       レベルm_level;
       int m_line;
};

#define __LOG(lvl)(Log(lvl、__FILE__、__LINE__))

#define LOG_ERR __LOG(Log :: Error)
#define LOG_WRN __LOG(Log :: Warning)
#define LOG_INF __LOG(Log :: Info)
#define LOG_DBG __LOG(Log :: Debug)

クラスMy_APIロガー
{{
公衆:
    virtual void log(const char * message)= 0;
};

クラスMY_APILoggerManager
{{
プライベート:
    static LoggerManager * s_inst;
    LoggerManager(){}
        仮想〜LoggerManager(){}
公衆:
    static LoggerManager * Instance();
    static void Clean();
    addLogger(Logger * newLogger、Log :: Level minlevel = Log :: Info);
        log(const char * file、int line、Log :: Level level、const char * message);
};

Cpp:

Log :: Log(レベルレベル、const char *ファイル、int行)
 :m_file(file)、m_level(level)、m_line(line)
{{
}

void Log :: operator()(const char * format、...)
{{
    va_list va;
    va_start(va、format);
    charメッセージ[LENGTH+1] = {0};

    _vsnprintf(message、LENGTH、format、va);

    va_end(va);

    LoggerManager :: Instance()-> log(m_file、m_line、m_level、message);


};

他のlibsとexeはこのように呼び出すことができるはずです。.hを含め、libにリンクするだけです。

LOG_INF( "Hello%s!"、 "world");

更新:ロギングメカニズムに必要な説明を追加しました。1つの方法は、シングルトンを使用して、実際のロギング用にサブクラス化されるインターフェースを提供することです。

マクロを使用する利点は、ログの場所を取得できることです。これは、場合によっては非常に興味深い情報になる可能性があります。すべてのロギングメカニズムを実装したくない場合は、マクロを通常のprintfに変換することもできます。

于 2009-07-16T10:14:48.630 に答える
0

あなたはgoogle-glogを使うことができます。使うのがいいと思います。

https://github.com/google/glog

ファイルごとのデバッグ値をサポートし、syslogにログを記録し、電子メールを送信し、その他の優れた機能をロードできます。

于 2009-07-16T10:20:56.573 に答える
-1

syslog-次に、syslog機能で使用することができます。

または、ユーザーがコールバックを指定できるようにします。

于 2009-07-16T09:53:19.263 に答える