如何在Linux上暂时捕获我自己的进程的stdout?

时间:2014-02-27 13:24:03

标签: linux qt qt4 posix stdout

我正在尝试在QTextWidget中显示方法的输出。该方法在stdout上打印json,它是我无法改变的第三方代码的一部分。

看起来像这样:

int iperf_json_finish(struct iperf_test *test)
{
    char *str;

    str = cJSON_Print(test->json_top);
    if (str == NULL)
        return -1;
    fputs(str, stdout);
    putchar('\n');
    fflush(stdout);
    free(str);
    cJSON_Delete(test->json_top);
    test->json_top = test->json_start = test->json_intervals = test->json_end = NULL;
    return 0;
}

那么,我该怎么做呢?我使用的是qt 4.8,不能使用像QMessageLogContext这样的东西。

1 个答案:

答案 0 :(得分:0)

  

如何在Linux上暂时捕获我自己进程的stdout?

诀窍是用你自己的管道描述符替换stdout文件描述符,用管道拦截输出,然后把原来的stdout放回来。

* NIX平台上的一般方案是:

  1. 保存stdout的原始文件描述符:int orig_stdin = dup(1);

  2. 准备管道:pipe(cap_stdout);

  3. 不要忘记刷新stdio:fflush(stdout);

  4. stdout替换为管道的书写端:dup2( 1, cap_stdout[1] );

  5. cap_stdout[0]文件描述符开始额外的线程读取。这是捕获截获数据的地方。

  6. 调用第三方库函数。

  7. 刷新stdio:fflush(stdout);

  8. 通知读取线程终止。

  9. 恢复标准输入:dup2( orig_stdin, 1 );

  10. 清理:close(cap_stdout[0]); close(cap_stdout[1]); close(orig_stdin);

  11. 您想要的数据是阅读主题已阅读的内容。

  12. 请注意,需要额外的线程,因为管道具有有限的缓冲区空间,并且没有读取器线程,对(管道)标准输出的写入将会阻塞,从而导致应用程序内部出现死锁。