【问题标题】:How to interact synchroniously with a process in Boost.Process 0.5如何与 Boost.Process 0.5 中的进程同步交互
【发布时间】:2015-04-02 07:02:51
【问题描述】:

这是一个关于Boost.Process 0.5 的问题,而不是以后的问题或earlier version,Boost 现在包含一个具有不同语法和功能的 Boost.Process 库。

假设我有一个简单的程序,它要求输入一个数字并返回另一个数字,即:

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

现在我想通过 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 作为接收器和源,但它不起作用。

我怎样才能让程序对执行的项目进行读写?

我找不到输入和输出都交错的示例。


编辑以显示具有早期版本库的工作示例

这是过去在 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");
}

【问题讨论】:

  • 改进的版本(设备对象的副本令人困惑):test.cppchild.cpp。它works some times 但我还没有找到如何让它可靠地工作
  • 有时有效? :( 。我刚刚复制了你的代码,它从一开始就卡住了(甚至没有打印第一行)。Boost 1.55,gcc 4.9.2,(或clang 3.5),Fedora 22。非常难过。我不得不再次恢复到 Boost.Process 0.3。
  • 这里:ubuntu,boost 1.57,gcc 4.8.2。现在,您是否暗示它适用于 BP0.3?
  • @sehe,不,在 Boost.Process 0.3 中,代码完全不同(没有 boost.iostream、sinks 等),并且很容易实现这个目标。顺便说一句,一个不相关的事情,我们之前确定接收器必须在执行后立即超出范围才能表现良好stackoverflow.com/questions/12329065/…
  • @sehe,我在最后添加并编辑了用于 Boost.Process GSOC2010 的完整代码。它看起来更容易(尽管仍然有很多容易出错的样板),最重要的是,它按预期工作(编译、运行和交互良好)。也许我在尝试同步使用 Boost.Process 0.5 时犯了一个错误,也许该库的设计考虑了异步使用(我不习惯)。

标签: c++ boost process synchronous boost-iostreams


【解决方案1】:

似乎是以下行中的错字:

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

必须是:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多