2015-04-02 1 views
1

Это вопрос о Boost.Process 0.5, а не какой-либо earlier versionКак взаимодействовать с моменты синхронно процесса в Boost.Process 0,5

Пусть у меня есть простая программа, которая попросить ряда и вернуть другой номер, а именно :

// ask.x, simple program with IO 
#include<iostream> 
int main(){ 
    double n; 
    std::cout << "number?" << std::endl; 
    std::cin >> n; 
    std::cout << n + 1 << std::endl; 
} 

Теперь я хочу, чтобы взаимодействовать с этой программой programmaticaly с помощью Boost.Process 0,5 (http://www.highscore.de/boost/process0.5/boost_process/tutorial.html). Когда я пытаюсь использовать библиотеку, я не получаю ожидаемого поведения, номер никогда не отправил в программу. (чтение первой строки в порядке). Я попытался написать обобщение примера, описанного в http://www.highscore.de/boost/process0.5/boost_process/tutorial.html#boost_process.tutorial.synchronous_i_o, но я потерпел неудачу.

MWE, в первой половине есть много необходимого шаблона, а также где я думаю, что совершу ошибку.

#include <boost/process.hpp> // version 0.5 
#include <boost/iostreams/device/file_descriptor.hpp> 
#include <boost/iostreams/stream.hpp> 
#include <string> 
#define ALSOSEND // for fully interactive case 
using namespace boost; 
int main() { 
    // Boilerplate code, see input only example here https://stackoverflow.com/questions/12329065/how-to-bind-program-termination-with-end-of-stream-in-boost-process-0-5 
    process::pipe pi = boost::process::create_pipe(); 
    process::pipe po = boost::process::create_pipe(); 
    { 
     iostreams::file_descriptor_sink sink(
      pi.sink, 
      iostreams::close_handle 
     ); 
     iostreams::file_descriptor_source source(
      po.source, 
      boost::iostreams::close_handle 
     ); 
     process::execute(
      process::initializers::run_exe("./ask.x"), 
      process::initializers::bind_stdout(sink) 
    #ifdef ALSOSEND 
      , process::initializers::bind_stdin(source) 
    #endif 
     ); 
    } 

    iostreams::file_descriptor_source fdsource(pi.source, iostreams::close_handle); 
    iostreams::stream<iostreams::file_descriptor_source> is(fdsource); 
    iostreams::file_descriptor_sink fdsink(po.source, iostreams::close_handle); 
    iostreams::stream<iostreams::file_descriptor_sink> os(fdsink); 

    // actual interaction with the process 
    std::string line; 
    std::getline(is, line); 
    assert(line == "number?"); 
    std::cout << "sending: " << "5" << std::endl; 
    os << "5" << std::endl; // RUN GETS STUCK HERE 
    std::getline(is, line); 
    assert(line == "6"); 
} 

Очевидно, что я не понимаю логику раковин и источников. Я также попытался использовать один pipe для раковины и источника, но это не сработало.

Как я могу сделать программу как для чтения, так и для записи из исполняемого проекта?

Я не могу найти пример, в котором ввод и вывод чередуются.


EDIT, чтобы показать рабочий пример с более ранней версией библиотеки

Это как делалось в Boost.Process GSOC2010 (не 0,5, как в вопросе выше) , обратите внимание, что фактическое взаимодействие с программой является таким же, как указано выше.

#include <boost/filesystem.hpp> // quasibug in process GSOC2010 needs to include filesystem BEFORE 
#include <boost/process.hpp> // version GSOC2010 (not 0.5) 
#include <boost/iostreams/device/file_descriptor.hpp> 
#include <boost/iostreams/stream.hpp> 
#include <string> 

using namespace boost; 
int main() { 
    // boiler plate code 
    std::vector<std::string> args; 
    process::context ctx; 
    ctx.process_name  = "askprocess"; 
    ctx.streams[process::stdout_id] = boost::process::behavior::pipe(); 
    ctx.streams[process::stdin_id ] = boost::process::behavior::pipe(); 

    process::child c = create_child("./ask", args, ctx); 
    process::pistream is(c.get_handle(process::stdout_id)); 
    process::postream os(c.get_handle(process::stdin_id)); 

    // actual interaction with the process 
    std::string line; 
    std::getline(is, line); 
    assert(line == "number?"); 
    std::cout << "sending: " << "5" << std::endl; 
    os << "5" << std::endl; // RUN GETS STUCK HERE 
    std::getline(is, line); 
    assert(line == "6"); 
} 
+1

Улучшенные версии (вы были запутанные копии объектов устройств): [тест .cpp] (http://paste.ubuntu.com/10722864/), [child.cpp] (http://paste.ubuntu.com/10722869/). Он [работает несколько раз] (http://paste.ubuntu.com/10722872/), но я не нашел, как заставить его работать надежно – sehe

+0

Он работает иногда? :(Я просто скопировал ваш код, и он застрял с самого начала (не печатает даже первую строку). Boost 1.55, gcc 4.9.2, (или clang 3.5), Fedora 22. Очень грустно. Еще раз я должен вернуться to Boost.Process 0.3. – alfC

+0

Здесь: ubuntu, boost 1.57, gcc 4.8.2. Теперь вы подразумеваете, что он работает в BP0.3? – sehe

ответ

2

Кажется, опечатка в следующей строке:

iostreams::file_descriptor_sink fdsink(po.source, iostreams::close_handle); 

Должно быть:

iostreams::file_descriptor_sink fdsink(po.sink, iostreams::close_handle); 
Смежные вопросы