2

我用 C++ 创建了一个 win32 控制台应用程序。我使用了一些 API(不是我的,我不能修改它的来源)。它的编写是为了将它的一些信息写入控制台屏幕而不是询问......每次我调用它(每秒 48 次)所以我想把它放到一些线程中并限制它的输出能力,但我需要得到当该线程将尝试输出一些对我很重要的消息时得到通知。我有标准字符串中的消息文本。如何使用 boost 在 C++ 中做这样的事情?

4

3 回答 3

2

这是一个疯狂的想法:

如果 lib 使用 cout/cerr,您可以将这些全局变量的 streambuf 替换为您自己的实现。它会在刷新/数据上检查一些线程局部变量以查看数据是否来自调用库的线程,然后将其路由到其他地方(即进入 std::string/std::ostringstream)而不是常规 cout/cerr 流缓冲区。(你应该保留它。)

如果它使用 c 的 stdout/stderr,我认为它会更难正确执行,但它可能仍然可行。您需要创建一些管道并来回路由东西。那么更多的是一个 C/unixy 问题,我对此还不太了解。:)

希望能帮助到你。

于 2010-11-25T18:53:52.300 回答
1

正如问题所描述的那样,我想不出一种在 Boost 中实现你想要的方法。

但是,这种 API 行为非常令人困惑。向控制台吐出大量输出有点反社会。您是否使用 API 库的调试版本?您确定没有办法配置 API 以便将此数据输出到不同的流,以便您可以在不捕获整个标准输出的情况下对其进行过滤?有没有办法减少输出量,让你只看到你关心的重要事件?

如果您确实需要捕获标准输出并对某些感兴趣的字符串(事件)进行操作,那么 Win32 提供了执行此操作的方法,但我真的会认真研究是否可以修改此输出以满足您的需求,然后再求助于那。

于 2010-11-25T16:54:05.760 回答
1

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;
}

本质上,此技巧的作用是允许您将所有写入重定向到stdoutstd::coutGetStdHandle(STD_OUTPUT_HANDLE)您选择的可写句柄 ( h)。当然,您可以使用CreatePipe创建可写句柄(h)并在另一个线程中从可读端读取。

编辑:如果您正在寻找一个跨平台的解决方案,请注意这个技巧在 POSIX 兼容的系统上更容易,因为dup2它是一个标准函数unistd.h并且“可写句柄”已经是描述符。

于 2010-11-26T02:57:47.227 回答