Boost:如何创建一个线程以便可以控制它的所有标准输出、标准错误?

发布于 2024-10-04 14:19:53 字数 194 浏览 7 评论 0原文

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

I create a win32 console app in C++. I use some API (not mine, and I can not modify its sources). It Is written so that it writes some of its info onto console screen not asking... each time I call it (48 times per second) So I want to put it into some thread and limit its output capabilities, but I need to get notified when that thread will try to output some message which is important for me. I have message text in standard string. How to do such thing in C++ using boost?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

萌无敌 2024-10-11 14:19:53

这是一个疯狂的想法:

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

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

希望有帮助。

Here's a crazy idea:

If the lib is using cout/cerr, you could replace the streambuf of these global variables with an implementation of your own. It would, on flush/data, check some thread-local variable to see if the data came from the thread that calls the library, then route it somewhere else (i.e. into a std::string/std::ostringstream) instead of to the regular cout/cerr streambufs. (Which you should keep around.)

If it's using c's stdout/stderr, I think it'd be harder to do properly, but it might be doable still. You'd need to create some pipes and route stuff back and forth. More of a C/unixy question then, which I don't know that much about... yet. :)

Hope it helps.

旧人九事 2024-10-11 14:19:53

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) code> 到您选择的可写句柄 (h)。当然,您可以使用 CreatePipe 创建可写句柄 (h) 并从另一个线程的可读端读取。

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

That feature does not exist in Boost. You can, however, use _dup2 to replace the standard out descriptor:

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

Essentially what this trick does is allow you to redirect all writes to stdout, std::cout, and GetStdHandle(STD_OUTPUT_HANDLE) to a writable handle of your choosing (h). Of course, you can use CreatePipe to create the writable handle (h) and read from the readable end in another thread.

EDIT: If you are looking for a cross-platform solution, note that this trick is even easier on POSIX-compatible systems because dup2 is a standard function in unistd.h and "writable handles" are already descriptors.

摘星┃星的人 2024-10-11 14:19:53

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

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

如果您确实需要捕获标准输出并对某些感兴趣的字符串(事件)进行操作,那么 Win32 提供了执行此操作的方法,但在诉诸之前,我真的会仔细研究一下是否可以修改此输出以满足您的需求那。

I cannot think of a way to achieve in Boost what you want, as the problem is described.

However, this API behaviour is very perplexing. Spitting out reams of output to the console is a bit antisocial. Are you using a Debug build of the API library? Are you sure there's no way to configure the API such that it outputs this data to a different stream, so that you can filter it without capturing the entire standard output? Is there a way to reduce the amount of output, so that you only see the important events you care about?

If you really need to capture standard output and act on certain strings (events) of interest, then Win32 provides ways to do this, but I'd really take a hard look at whether this output can be modified to meet your needs before resorting to that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文