プログラムを書こう!

実務や自作アプリ開発で習得した役に立つソフトウェア技術情報を発信するブログ

MFCでログにファイル名、関数名、行番号、メッセージを表示する。

この記事は2019年02月22日に投稿しました。

f:id:paveway:20190914064630j:plain

目次

  1. はじめに
  2. MFCでログにファイル名、関数名、行番号、メッセージを表示する
  3. おわりに

かんたん Visual C++[改訂2版]

かんたん Visual C++[改訂2版]

1. はじめに

こんにちは、iOSのエディタアプリPWEditorの開発者の二俣です。
今回は業務で使用しているMFCでログにファイル名、関数名、行番号、メッセージを表示する方法についてです。

目次へ

2. MFCでログにファイル名、関数名、行番号、メッセージを表示する

MFCでログにファイル名、関数名、行番号、メッセージを表示する方法ですが、以下のような処理になります。

ポイントはLOGマクロです。

LOGマクロで呼び出しているのが以下の定義済みマクロです。
これらは呼び出し時点の、ファイルパス名、関数名、行番号、可変長引数に展開されます。
そのためこれらのマクロをログ出力する関数本体(例では"Log"関数)で呼び出すと、常にLog関数の情報で展開されます。
そのためLOGマクロで展開する必要があります。

マクロ名 内容
__FILE__ ファイルパス名
ファイル名ではないので注意
__FUNCTION__ 関数名
__LINE__ 行番号
__VA_ARGS__ 可変長引数

Log関数の現在時刻を取得する方法は

paveway.hatenablog.com

で紹介した方法です。

またファイルパス名からファイル名を取得する方法は

paveway.hatenablog.com

で紹介した方法です。

可変長引数を1つの文字列に整形する方法は

paveway.hatenablog.com

で紹介した方法です。

Log.h
// ログ文字列を出力する関数のプロトタイプ宣言
// (使う側は直接この関数を呼び出さないこと)
CString Log(CString file, CString function, int line, CString fmt, ...);

// 使う側が呼び出すマクロ
#define LOG(fmt, ...) Log(_T(__FILE__), _T(__FUNCTION__), __LINE__, fmt, ##__VA_ARGS__)

// 可変長引数を1つの文字列に整形する際使用するバッファサイズ
#define BUFFER_SIZE    (1024)
Log.cpp
/**
 * @brief コンソールにログ文字列を出力します。
 *        "LOG"マクロから呼び出されます。
 *        出力フォーマット:YYYY/MM/DD HH:MM:SS ファイル名 関数名(行番号) メッセージ
 *
 * @param [in] file ファイルパス名
 * @param [in] function 関数名
 * @param [in] line 行番号
 * @param [in] fmt フォーマット文字列
 * @param [in] ... 可変長引数
 * @return フォーマットされたログ文字列
 */
CString Log(CString file, CString fuction, int line, CString fmt, ...)
{
    // ログ出力する時点の年月日時分秒(YYYY/MM/DD HH:MM:SS)を取得します。
    CTime cTime = CTime::GetCurrentTime();
    CString time = cTime.Format("%Y/%m/Td %H:%M:%S");

    // ファイルパス名からファイル名のみ取得します。
    CStringArray items;
    int pos = 0;
    CString item;
    while ((item = file.Tokenize(_T("\\"), pos)) != "")
    {
        items.Add(item)
    }
    int index = items.GetCount() - 1;
    CString fileName = items.GetAt(index);

    // 可変長引数を1つの文字列に整形します。
    va_list args;
    va_start(args, fmt);
    TCHAR buffer[BUFFER_SIZE + 1];
    ZeroMemory(&buffer[0], sizeof(buffer));
    _vstprintf(buffer, bufferSize, fmt, args);
    va_end(args);

    // 出力するフォーマット文字列に整形します。
    CString log;
    log.Format(_T("%s %s %s(%d) %s\n"), time, fileName, function, line, buffer);
    return log;
}

使用例

Main.cpp
#include "atdafx.h"
#include <afxwin.h>
#include <Windows.h>

int func(int a, int b)
{
    OutDebugString(LOG(_T("a=%d b=%d"), a, b));

    int c = a + b;

    OutDebugString(LOG(_T("c=%d"), c));
    return c;
}

int main(void)
{
    int c = func(1, 2);
    return 0;
}
実行結果
2019/02/22 07:10:15 Main.cpp func(7) a=1 b=2
2019/02/22 07:10:15 Main.cpp func(11) c=3

目次へ

3. おわりに

ログ出力の際、ログ出力したファイル名、関数名、行番号は必要な情報です。
これが定義済みマクロで取得できるのは便利です。

未経験から最短でエンジニア転職を目指す

標準講座MFC6.0―Visual C++による効率的なWindowsプログラミング (Programmer’s SELECTION)

標準講座MFC6.0―Visual C++による効率的なWindowsプログラミング (Programmer’s SELECTION)

  • 作者: ハーバートシルト,田中正造,Herbert Schildt,コスモワークス
  • 出版社/メーカー: 翔泳社
  • 発売日: 1999/04/01
  • メディア: 単行本
  • 購入: 11人 クリック: 39回
  • この商品を含むブログ (4件) を見る

紹介している一部の記事のコードはGitlabで公開しています。
興味のある方は覗いてみてください。

目次へ


私が勤務しているニューラルでは、主に組み込み系ソフトの開発を行っております。
弊社製品のハイブリッドOS Bi-OSは高い技術力を評価されており、特に制御系や通信系を得意としています。
私自身はiOSモバイルアプリウィンドウズアプリを得意としております。
ソフトウェア開発に関して相談などございましたら、お気軽にご連絡ください。

また一緒に働きたい技術者の方も随時募集中です。
興味がありましたらご連絡ください。

EMAIL : info-nr@newral.co.jp / m-futamata@newral.co.jp
TEL : 042-523-3663
FAX : 042-540-1688

目次へ