可変パラメーターマクロ

最近、私は1つのオープンソースプロジェクトに対処する必要がありました。 1つの間違いに対処する必要がありました。 エラーは浮かんでいて、30分後には奴隷になって、スタンドだけに現れました。 そして、それは常にそうではありません。 したがって、コードの特定のセクションを記録することが決定されました。



したがって、単純な関数が作成されました。

void dbg(const char * AMsg);
      
      



これはログに行を書きました。 そのような機能は十分ではなく、次の形式で書き直されたことがすぐに判明しました。

 void dbg(const char * AFmt, ...);
      
      



つまり 現在、彼女はvfprintf()関数を使用して、フォーマットされた文字列をファイルに書き込みました。 呼び出しの数が増えるにつれて、ファイルにさらに2つのパラメーター、つまり__LINE__と__FILE__を書き込みたいと思いました。 各関数呼び出しでこれらの2つのパラメーターを転送したくなかったため、dbg()関数のマクロラッパーを作成し、可変数のパラメーターを取得し、元の関数を呼び出し、最初の2つのパラメーターでファイル名と行番号を渡すことにしました。



グーグル、私はかなりいい解決策を見つけました-クラスを記述し、その中の演算子()をオーバーロードします。 テストプロジェクトをスケッチし、新しいマクロと修正された関数をテストし、結果に満足しました。 その後、ファイルを元のプロジェクトに接続し、「StdAfx.h」のhファイルをヒントして、「ビルド」をクリックしました。 そして、私は深い失望に追われました。 プロジェクトの一部が純粋なCで記述されていることが判明しました。これは私のクラスが念頭に置いていました。



まだグーグルで、私はそのような解決策を見つけまし 。 しかし、悲しいかな、私はVC6を使用しました...



そして、アイデアが思いつきました-まあ、マクロが__FILE__および__LINE__パラメーターを受け取る関数に置き換えられた場合、それらをどこかに保存して、元のdbg()関数へのポインターを返すということです。 そして、この関数は保存されたパラメーターを読み取り、ファイルに書き込みます。 グローバル変数にパラメーターを保存することにしました。 また、変数自体は、マルチスレッド作業中にレーキにぶつからないように、__ declspec(スレッド)として宣言します。 Bは最後に何が起こったかです:



hファイル

 // File debug_info.h #ifndef __DEBUG_INFO_H #define __DEBUG_INFO_H //     ,   typedef void (* DbgFuncType)(const char * AFmt, ...); // ,   __FILE__  __LINE__,       #ifdef __cplusplus extern "C" #endif DbgFuncType DbgFuncRet(const char* AFile, int ALine); //    #define dbg DbgFuncRet(__FILE__, __LINE__) #endif
      
      



cppファイル

 // File debug_info.h #include "StdAfx.h" #include <stdio.h> #include <stdarg.h> __declspec(thread) char __File__[MAX_PATH]; __declspec(thread) int __Line__; void DbgFunc(const char * AFmt, ...) { FILE * log; if (fopen_s(&log, log_name, "a")) return; va_list args; va_start(args, AFmt); vfprintf(log, AFmt, args); fprintf(log, "File: \"%s\", Line: %d\n", __File__, __Line__); fclose(log); va_end(args); } DbgFuncType DbgFuncRet(const char* AFile, int ALine) { strcpy_s(__File__, MAX_PATH, AFile); __Line__ = ALine; return &DbgFunc; }
      
      





以上です。 私が詳しく述べたいのは、関数DbgFuncRet()の宣言だけです。

 #ifdef __cplusplus extern "C" #endif DbgFuncType DbgFuncRet(const char* AFile, int ALine);
      
      



なぜなら ヘッダーはcファイルとcppファイルの両方で接続されているため、名前変換プログラムは関数に異なる装飾を使用します。 そして、そのような発表は、コンパイラに常にC装飾を使用するように伝えます。



All Articles