OutputDebugString関数
の使い方と、printf
の様な可変数でのOutputDebugString
使い方については、以下にて紹介されている
link:その3 デバッグウィンドウを知らないと大変です
しかし、今どきprintf系
は使用したくなかったので、C++17
までは、可変引数をBoost Formatで無理矢理実現してきた
ただ、いつの間にかにC++20
になっていて、std::format
が導入されたので、std::format
対応版のOutputDebugString 可変数化
に修正したので、それのメモです
link:C++20の文字列フォーマットライブラリ std::format
実行イメージと結果
任意の場所で、自作関数MyOutputDbgStr(std::format記述)
を呼び出す
MyOutputDbgStr(TEXT("テストコード \n"));
MyOutputDbgStr(TEXT("テストコード i= {} \n"), 1);
MyOutputDbgStr(TEXT("テストコード i= {},{} \n"), 2, TEXT("msg"));
// MyOutputDbgStr(TEXT("テストコード i= {},{} \n"), 3 ); //{}が多いと、コンパイルは通るが、実行時例外エラー発生する。なお呼出し履歴を辿れば呼び出し元が分かる
MyOutputDbgStr(TEXT("テストコード i= \n"), 4 ); //{}がないときは、文字列のまま出力(引数無視)
MyOutputDbgStr(TEXT("テストコード i={} \n"), 5, 100); //{}が少ないときも、余剰引数無視
// MyOutputDbgStr(TEXT("テストコード i={},{} \n"), 6, "100");//引数の文字列がUNICODEでないので、コンパイルエラー
// MyOutputDbgStr("テストコード i={} \n", 7); //UNICODEでないので、コンパイルエラー
VisualStudioでのデバッグ出力
※接頭部に呼び出し元ファイル、行数、関数名も自動追記しているので、Visual Studioデバッガならダブルクリックのジャンプ対応
環境
- Windows 10
- Visual Studio 2022 C++
- (デバッグ構成プロパティ-全般で、ISO C++ 20 標準 (/std:c++20) )
- (デバッグ構成プロパティ-詳細で、Unicode 文字セットを使用する)
作成
-
デバッグ関数呼び出し元の情報を、接頭に
#define
追記する
※なお、従来、__FILE__
、__LINE__
、__FUNC__
を使用していたが、最近のコンパイル?でうまく展開できなかったので?、std::source_location
を使用した
(L__FUNC__:定義されていない識別子です。
となる。define分けても駄目だった)C++#define MyOutputDbgStr( ... ) MyOutputDbgStr_( std::source_location::current() , __VA_ARGS__ )
-
文字列を整形して
OutputDebugString
に投げる-
std::format
を使って、接頭に__FILE__(__LINE__):__FUNC__:
の文字列を作成する
(この文字列の存在により、Visual Studioデバッガのダブルクリックジャンプに対応する、気がする) -
std::string
をstd::wstring
に変換する
UNICODE環境の為、OutputDebugString
はOutputDebugStringW
を呼び出すため。
ansi_to_wide
は、std::string
をstd::wstring
に変換する自作関数(適宜実装、static inline宣言必須?
) - 残りの文字列(
Args
)の処理は、std::format
に任せる -
OutputDebugString
出力時は、厳密には、mutex
した方がいいらしい?別途検討 -
OutputDebugString
出力する
C++template<typename... Args> void MyOutputDbgStr_(const std::source_location location, std::wformat_string<Args...> s, Args&&... args) { std::string fmt = std::format("{}({}):{}:", location.file_name(), location.line() , location.function_name() ); std::wstring wfmt = ansi_to_wide(fmt); wfmt += std::format(s, std::forward<Args>(args)...); // std::lock_guard<std::mutex> lock(mtx_OutputDebugStr); // mtxを使ってロックする ::OutputDebugString(wfmt.c_str()); }
-