LoginSignup
0
0

OutputDebugString 可変数で出力 メモ

Posted at

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記述)を呼び出す

C++
    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でのデバッグ出力
2024-02-05_115906.png
※接頭部に呼び出し元ファイル、行数、関数名も自動追記しているので、Visual Studioデバッガならダブルクリックのジャンプ対応

環境

  • Windows 10
  • Visual Studio 2022 C++
  • (デバッグ構成プロパティ-全般で、ISO C++ 20 標準 (/std:c++20) )
  • (デバッグ構成プロパティ-詳細で、Unicode 文字セットを使用する)

作成

  1. デバッグ関数呼び出し元の情報を、接頭に#define追記する
    ※なお、従来、__FILE____LINE____FUNC__を使用していたが、最近のコンパイル?でうまく展開できなかったので?、std::source_locationを使用した
    L__FUNC__:定義されていない識別子です。となる。define分けても駄目だった)

    C++
    #define MyOutputDbgStr( ... ) MyOutputDbgStr_( std::source_location::current() , __VA_ARGS__ )
    

  2. 文字列を整形してOutputDebugStringに投げる

    1. std::formatを使って、接頭に__FILE__(__LINE__):__FUNC__:の文字列を作成する
      (この文字列の存在により、Visual Studioデバッガのダブルクリックジャンプに対応する、気がする)
    2. std::stringstd::wstringに変換する
      UNICODE環境の為、OutputDebugStringOutputDebugStringWを呼び出すため。
      ansi_to_wideは、std::stringstd::wstringに変換する自作関数(適宜実装、static inline宣言必須?)
    3. 残りの文字列(Args)の処理は、std::formatに任せる
    4. OutputDebugString出力時は、厳密には、mutexした方がいいらしい?別途検討
    5. 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());
    }
    
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0