moghya
moghya

Reputation: 864

read stdout of a process in itself using c++

Consider we have some_function and it prints result to stdout instead returning it.Changing it's defination is out of our scope and there's no alternative to it. We're left with option of reading it from stdout. So the question.

How to read stdout of C++ program in itself.

It is possible to get pid I searched if we can get fd of the same programm but I'm not able to find anything.

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

How to attach pipe to same process i.e instead of creating child process.

Some might think of creating child process and call some_function in it, to be able to read its stdout in parent process, but No, some_function depends on process which calls it and hence we want to call it the very process instead of creating child process.

Upvotes: 4

Views: 6509

Answers (2)

How to read stdout of C++ program in itself?

There are very few reasons to do that and that is usually (but not always) a design bug.

Be aware of an important thing (at least in a single-threaded program). If your program is both reading from its "stdout" and writing (as usual) in it, it could be stuck in a deadlock: unable to read so not reaching any output routine, (or unable to write because the pipe is full).

So a program which both reads and writes the same thing (actually, the two sides of the same pipe(7)) should use some multiplexing call like poll(2). See also this.

Once you understand that, you'll have some event loop. And before that, you'll make a pipe(7) using pipe(2) (and dup2(2)).

However, pipe to self is a good thing in some signal(7) handling (see signal-safety(7)). That trick is even recommended in Qt Unix signal handling.

Read more about Unix system programming, e.g. ALP or some newer book. Read also intro(2) & syscalls(2).

I have looked for pipe and it requires fd

Wrong. Read much more carefully pipe(2); on success it fills an array of two file descriptors. Of course it could fail (see errno(3) & perror(3) & strerror(3))

Maybe you just need popen(3). Or std::ostringstream. Or open_memstream(3).

Consider we have some_function and it prints result to stdout instead returning it. Changing it's definition is out of our scope and there's no alternative to it

If some_function is your code, or is some free software, you could and probably should improve it to give a result somewhere....

Upvotes: 3

Andrew Henle
Andrew Henle

Reputation: 1

This isn't hard to do, but IMO it's quite a hack, and it won't work with a multithreaded program:

// 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

Error checking, proper headers, syncing C stdout with C++ cout, and reading from and cleaning up the temp file are left as exercises... ;-)

Note that you can't safely use a pipe - the function can write enough to fill up the pipe, and you can't read from the pipe because you've called the function.

Upvotes: 6

Related Questions