C++ で win32 コンソール アプリを作成します。私はいくつかの API を使用しています (私のものではなく、そのソースを変更することはできません)。コンソール画面に情報の一部を要求せずに書き込むように書かれています...呼び出すたびに(1秒あたり48回)、それをスレッドに入れて出力機能を制限したいのですが、取得する必要がありますそのスレッドが私にとって重要なメッセージを出力しようとすると通知されます。標準文字列のメッセージ テキストがあります。ブーストを使用してC ++でそのようなことを行う方法は?
3 に答える
ここにクレイジーなアイデアがあります:
lib が cout/cerr を使用している場合、これらのグローバル変数の streambuf を独自の実装に置き換えることができます。フラッシュ/データで、スレッドローカル変数をチェックして、データがライブラリを呼び出すスレッドからのものかどうかを確認し、別の場所にルーティングします (つまり、std::string/std::ostringstream にルーティングします)。通常の cout/cerr ストリームバッファ。(これは手元に置いておく必要があります。)
C の stdout/stderr を使用している場合、適切に実行するのは難しいと思いますが、それでも実行できる可能性があります。いくつかのパイプを作成し、物を前後にルーティングする必要があります。それから、C/unixy に関する質問ですが、私はそれについてあまり知りません... まだ。:)
それが役に立てば幸い。
問題が説明されているように、ブーストであなたが望むものを達成する方法は考えられません。
ただし、この API の動作は非常に複雑です。大量の出力をコンソールに吐き出すのは、少し反社会的です。API ライブラリのデバッグ ビルドを使用していますか? このデータを別のストリームに出力するように API を構成する方法がないので、標準出力全体をキャプチャせずにフィルター処理できますか? 出力の量を減らして、関心のある重要なイベントのみを表示する方法はありますか?
標準出力をキャプチャし、関心のある特定の文字列 (イベント) に作用する必要がある場合は、Win32 がこれを行う方法を提供しますが、必要に応じてこの出力を変更できるかどうかをよく調べてから、それ。
その機能は Boost にはありません。_dup2
ただし、標準出力記述子を置き換えるために使用できます。
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <io.h>
#include <iostream>
#include <windows.h>
int main()
{
HANDLE h = CreateFile(TEXT("test.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (0 == SetStdHandle(STD_OUTPUT_HANDLE, h)) {
std::fprintf(stderr, "`SetStdHandle` failed with error %d\n", (int)GetLastError());
return EXIT_FAILURE;
}
int h_desc = _open_osfhandle((long)h, 0);
_dup2(h_desc, STDOUT_FILENO);
std::printf("test\r\n"); // This actually writes to `h`.
std::fflush(stdout);
std::cout << "another test" << std::endl; // Also writes to `h`
CloseHandle(h);
return EXIT_SUCCESS;
}
基本的に、このトリックが行うことは、すべての書き込みをstdout
、std::cout
、およびGetStdHandle(STD_OUTPUT_HANDLE)
選択した書き込み可能なハンドル ( h
) にリダイレクトできるようにすることです。もちろん、 を使用CreatePipe
して書き込み可能なハンドル ( h
) を作成し、別のスレッドで読み取り可能な側から読み取ることができます。
編集:クロスプラットフォームのソリューションを探している場合、POSIX 互換システムではこのトリックがさらに簡単であることに注意してdup2
くださいunistd.h
。