使用c ++

时间:2018-04-05 14:11:16

标签: c++ unix process stdout pid

考虑我们有some_function,它会将结果打印到stdout而不是返回它。更改它的定义超出了我们的范围,除此之外别无选择。我们可以选择从stdout阅读。所以问题。

如何阅读C ++程序的stdout本身。

如果我们可以获得相同程序的pid但我无法找到任何内容,则可以fd我搜索。

#include <unistd.h>
#include <sys/types.h>
#include <iostream>
void some_function(){
    std::cout<<"Hello World";
}

int main(){


    int pid = ::getpid();
    string s = //What to write here.

    cout<<"Printing";

    some_function(); //This function prints "Hello World" to screen

    cout<<s; //"PrintingHello World"
    return  0;
}

如何将管道连接到同一个进程,而不是创建子进程。

有些人可能会考虑创建子流程并在其中调用some_function,以便能够在父流程中读取其stdout,但不,some_function取决于调用它的流程和因此,我们希望将其称为过程,而不是创建子过程。

2 个答案:

答案 0 :(得分:2)

  

如何阅读C ++程序的stdout本身?

这样做的理由很少,而通常是(但并不总是)设计错误。

注意一件重要的事情(至少在单线程程序中)。如果你的程序都是从&#34; stdout&#34;并且(像往常一样)写入它,它可能陷入死锁:无法读取因此无法达到任何输出例程,(或因管道已满而无法写入)。

因此,读取和写入相同内容(实际上,同一pipe(7)的两边)的程序应该使用一些多路复用调用,如poll(2)。另请参阅this

一旦你理解了这一点,你就会有一些event loop。在此之前,您将使用pipe(7)(和pipe(2))制作dup2(2)

然而,在某些signal(7)处理中管道自我是一件好事(参见signal-safety(7))Qt Unix signal handling甚至建议使用这个技巧。

阅读有关Unix系统编程的更多信息,例如ALP或一些较新的书。另请阅读intro(2)&amp; syscalls(2)

  

我找了管道,它需要fd

错误。仔细阅读pipe(2);成功时,填充两个file descriptors的数组。当然可能会失败(见errno(3)&amp; perror(3)&amp; strerror(3)

也许你只需要popen(3)。或std::ostringstream。或open_memstream(3)

  

考虑我们有some_function并将结果打印到stdout而不是返回它。改变它的定义超出了我们的范围,除此之外别无选择

如果some_function是您的代码,或者是某些free software,您可以并且可能应该对其进行改进以在某处提供结果....

答案 1 :(得分:2)

这并不难做到,但是IMO非常糟糕,并且它不会使用多线程程序:

// make a temp file to store the function's stdout
int newStdOut = mkstemp( "/tmp/stdout.XXXXXXX" );

// save the original stdout
int tmpStdOut = dup( STDOUT_FILENO );

// clear stdout
fflush( stdout );

// now point the stdout file descriptor to the file
dup2( newStdOut, STDOUT_FILENO );

// call the function we want to collect the stdout from
some_function();

// make sure stdout is empty
fflush( stdout );

// restore original stdout
dup2( tmpStdOut, STDOUT_FILENO );

// the tmp file now contains whatever some_function() wrote to stdout

检查错误,使用正确的标头,使用C ++ stdout同步C cout,并将读取和清理临时文件留作练习...; - )

请注意,您无法安全地使用管道 - 该功能可以写入足以填满管道,并且您无法从管道中读取,因为您已经调用了该功能。