Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to capture standard output of process using Boost.Process

Currently am using Boost.Process from the Boost sandbox, and am having issues getting it to capture my standard output properly; wondering if someone can give me a second pair of eyeballs into what I might be doing wrong.

I'm trying to take thumbnails out of RAW camera images using DCRAW (latest version), and capture them for conversion to QT QImage's.

The process launch function:

namespace bf = ::boost::filesystem; 
namespace bp = ::boost::process;

QImage DCRawInterface::convertRawImage(string path) {
    // commandline:  dcraw -e -c <srcfile>  -> piped to stdout.
    if ( bf::exists( path ) ) {
        std::string exec = "bin\\dcraw.exe";

        std::vector<std::string> args;
        args.push_back("-v");
        args.push_back("-c");
        args.push_back("-e");
        args.push_back(path);

        bp::context ctx;
        ctx.stdout_behavior = bp::capture_stream();

        bp::child c = bp::launch(exec, args, ctx);

        bp::pistream &is = c.get_stdout();
        ofstream output("C:\\temp\\testcfk.jpg");
        streamcopy(is, output);
    }
    return (NULL);
}


inline void streamcopy(std::istream& input, std::ostream& out) {
    char buffer[4096];
    int i = 0;
    while (!input.eof() ) {
        memset(buffer, 0, sizeof(buffer));
        int bytes = input.readsome(buffer, sizeof buffer);
        out.write(buffer, bytes);
        i++;
    }
}

Invoking the converter:

DCRawInterface DcRaw;
DcRaw.convertRawImage("test/CFK_2439.NEF"); 

The goal is to simply verify that I can copy the input stream to an output file.

Currently, if I comment out the following line:

    args.push_back("-c");

then the thumbnail is written by DCRAW to the source directory with a name of CFK_2439.thumb.jpg, which proves to me that the process is getting invoked with the right arguments. What's not happening is connecting to the output pipe properly.

FWIW: I'm performing this test on Windows XP under Eclipse 3.5/Latest MingW (GCC 4.4).

[UPDATE]

From debugging, it would appear that by the time the code reaches streamcopy, the file/pipe is already closed - bytes = input.readsome(...) is never any value other than 0.

like image 471
Chris K Avatar asked Mar 16 '10 20:03

Chris K


2 Answers

Well I think that you need to redirect correctly the output stream. In my application something like this works :

[...]

bp::command_line cl(_commandLine);
bp::launcher l;

l.set_stdout_behavior(bp::redirect_stream);
l.set_stdin_behavior(bp::redirect_stream);
l.set_merge_out_err(true);

bp::child c = l.start(cl);
bp::pistream& is = c.get_stdout();

string result;
string line;
while (std::getline(is, line) && !_isStopped)
{
    result += line;
}

c.wait();

[...]

Without the redirect the stdout will go nowhere if I remember correctly. It is a good practice to wait for the process end if you want to get the whole output.

EDIT:

I'm on Linux with perhaps an old version of boost.process. i realize that your code is similar to the snippet I gave you. The c.wait() might be the key ...

EDIT: Boost.process 0.1 :-)

like image 59
neuro Avatar answered Sep 29 '22 19:09

neuro


If migrating to the "latest" boost.process isn't an issue (as you sure know, there are several variants for this library) ,you could use the following (http://www.highscore.de/boost/process0.5/)

file_descriptor_sink sink("stdout.txt");
execute(
    run_exe("test.exe"),
    bind_stdout(sink)
);
like image 37
Shmil The Cat Avatar answered Sep 29 '22 21:09

Shmil The Cat