C标准输出的替代方案

3

我在项目中使用了一个库。这个库有时会将一些消息打印到标准输出(stdout)上。对我来说,这是个问题,因为这些消息与应用程序的消息混杂在一起。停止这种行为或将它们打印到另一个窗口中都会很有用。我使用C语言和Mingw32环境。我该如何做?谢谢。


5
通常情况下,库函数不应该写入 stdout,除非这是函数的目的。你确定它没有写入 stderr 吗? - Barmar
1
在这种情况下,该库将写入标准输出,因为如果我插入“fclose(stderr)”,则什么也不会发生,否则我关闭标准输出,屏幕就会清除。 - Giancarlo
1
你的应用程序是单线程的,并且保证只有单线程吗?如果是这样,那么可以使用调用重定向stdout到其他目标的调用来包装对这个奇怪库的所有调用,然后调用该库,最后恢复stdout。如果你的应用程序或库是多线程的,那么没有安全的方法来做到这一点。 - Andrew Henle
1个回答

0

你可能可以(非可移植地)将 stdout 与另一个流进行交换:

#include <stdio.h>

FILE *devnull;
#define SWAPSTDOUT() do{ FILE *tmp = stdout;  stdout = devnull; devnull = tmp; }while(0)

int main(void)
{
    /*program initialization*/
    if(0==(devnull= fopen("/dev/null", "r"))) return 1;

    fputs("your code 0\n",stdout);
    SWAPSTDOUT();
    fputs("library code 0\n",stdout); //should be silent
    SWAPSTDOUT();
    fputs("your code 1\n", stdout);
}

不幸的是,这对硬编码了stdout(例如printfputs)的函数可能行不通。

如果您在POSIX平台上,可能会有freopen,但如果无法保存原始流,则帮助不大。但是,在POSIX上,您可以fflush(stdout),然后洗牌底层文件描述符,这应该是相当可靠的:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int devnull, tmp;
int swapstdout(void);

int main(void)
{
    /*program initialization*/
    if(0>(devnull=open("/dev/null", O_RDONLY))) return EXIT_FAILURE;
    if(0>(tmp=dup(devnull))) return EXIT_FAILURE; //reserve a fd spot


    fputs("your code 0\n",stdout);
    if(0>swapstdout()) return EXIT_FAILURE:
    fputs("library code 0\n",stdout); //should be silent
    if(0>swapstdout()) return EXIT_FAILURE:
    fputs("your code 1\n", stdout);
}

int swapstdout(void)
{
    if(0>fflush(stdout)) return -1;
    if(0>dup2(STDOUT_FILENO,tmp)) return -1; /*really shouldn't happen*/
    if(0>dup2(devnull,STDOUT_FILENO)) return -1; /*really shouldn't happen*/
    if(0>tmp=dup(devnull)) return -1; /*really shouldn't happen unless we're multithreaded and another thread steals the fd spot*/
}

任何一种解决方案都取决于您的代码是否是单线程的。

无论如何,良好的库函数应该让它们不拥有的文件保持原样,除非您明确要求它们对这些文件进行操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接