Невозможно зафиксировать стандартный вывод процесса с помощью Boost.Process

В настоящее время я использую Boost.Process из песочницы Boost, и у меня возникают проблемы с его правильным захватом моего стандартного вывода; интересно, может ли кто-нибудь дать мне вторую пару глазных яблок в том, что я могу делать неправильно.

Я пытаюсь извлечь миниатюры из изображений камеры RAW с помощью DCRAW (последняя версия) и захватить их для преобразования в QT QImage.

Функция запуска процесса:

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

Вызов преобразователя:

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

Цель состоит в том, чтобы просто проверить, могу ли я скопировать входной поток в выходной файл.

В настоящее время, если я прокомментирую следующую строку:

    args.push_back("-c");

затем миниатюра записывается DCRAW в исходный каталог с именем CFK_2439.thumb.jpg, что доказывает мне, что процесс вызывается с правильными аргументами. Чего не происходит, так это правильного подключения к выходной трубе.

FWIW: я выполняю этот тест в Windows XP с Eclipse 3.5/Latest MingW (GCC 4.4).

[ОБНОВИТЬ]

Из отладки видно, что к тому времени, когда код достигает потоковой копии, файл/канал уже закрыт - bytes = input.readsome(...) никогда не имеет значения, отличного от 0.


person Chris K    schedule 16.03.2010    source источник
comment
Вероятно, это не главная проблема, но output``ofstream следует открывать в двоичном режиме. Также: streamcopy можно упростить до out << input.rdbuf();   -  person Éric Malenfant    schedule 16.03.2010
comment
Хороший вызов input.rdbuf(). На самом деле я использовал это до того, как написал потоковую копию, чтобы посмотреть, что происходит под капотом.   -  person Chris K    schedule 17.03.2010


Ответы (2)


Ну я думаю, что вам нужно правильно перенаправить поток вывода. В моем приложении работает что-то вроде этого:

[...]

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();

[...]

Без перенаправления стандартный вывод никуда не денется, если я правильно помню. Хорошей практикой является дождаться завершения процесса, если вы хотите получить весь вывод.

РЕДАКТИРОВАТЬ:

Я использую Linux, возможно, со старой версией boost.process. Я понимаю, что ваш код похож на фрагмент, который я вам дал. c.wait() может быть ключом...

РЕДАКТИРОВАТЬ: Boost.process 0.1 :-)

person neuro    schedule 02.04.2010

Если переход на «последний» boost.process не является проблемой (как вы наверняка знаете, существует несколько вариантов этой библиотеки), вы можете использовать следующее (http://www.highscore.de/boost/process0.5/)

file_descriptor_sink sink("stdout.txt");
execute(
    run_exe("test.exe"),
    bind_stdout(sink)
);
person Shmil The Cat    schedule 11.03.2013