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.
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 :-)
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)
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With