1

我有一些简单的应用程序:

//first.exe

int main()
{
  std::cout << "1" << std::endl;
  std::cout << "2" << std::endl;
  std::cout << "3" << std::endl;

  std::cin.get();

  return 0;
}

当作为子进程运行的应用程序的标准输出中出现“2”时,我想在单独的应用程序中调用回调:

//second.exe

int main()
{
  boost::asio::io_context context;
  boost::process::async_pipe out(context);
  boost::asio::streambuf buffer;

  boost::process::child("first.exe", boost::process::std_out > out);

  boost::asio::async_read_until(out, buffer, "2", [](boost::system::error_code code, std::size_t size)
  {
    //do something
  });

  context.run();

  return 0;
}

问题是我必须std::cin.get()在子进程中按下父进程中的任何按钮才能使 io_context 执行回调函数。你有什么建议让它按预期工作吗?

4

1 回答 1

1

在这种情况下,我认为您不需要做任何事情(std::cin读取可能会失败):

Live On Coliru

#include <boost/process.hpp>
#include <boost/asio.hpp>
#include <boost/process/async.hpp>
#include <iostream>
#include <iomanip>

int main()
{
    namespace bp = boost::process;
    boost::asio::io_context context;
    bp::async_pipe out(context);

    bp::child c("./first.exe", bp::std_out > out);

    boost::asio::streambuf buffer;
    boost::asio::async_read_until(out, buffer, "2", [&](boost::system::error_code code, std::size_t size) {
        if (code) {
            std::cerr << "Oops: " << code.message() << std::endl;
        } else {
            std::cerr << "received: " << size << " bytes: ";

            auto b = buffers_begin(buffer.data()), m = b+size, e = buffers_end(buffer.data());

            std::clog << std::quoted(std::string(b, m)) << std::endl;
            std::clog << "Note that we read more bytes: " << std::quoted(std::string(m, e)) << std::endl;

            buffer.consume(size);
        }
    });

    context.run();
    return c.exit_code();
}

印刷

received: 3 bytes: "1
2"
Note that we read more bytes: "
3
"

清洁器

为了清洁,您可以简单地关闭std_in

bp::child c("./first.exe", bp::std_out > out, bp::std_in.close());

为了正确起见,还要添加异步 io 的上下文:

bp::child c("./first.exe", bp::std_out > out, bp::std_in.close(), context);

这些都有效(见现场)。

更复杂

如果你真的需要提供输入来获得输出怎么办?或者您需要根据输出提供输入?那么评论者是对的:将管道附加到 std_in (或异步写入缓冲区)。

发送固定缓冲区

Live On Coliru

  • 第一个.cpp

    #include <iostream>
    int main() {
        using namespace std;
        string s;
        while (cin >> s)
            cout << "reversed: " << string(s.rbegin(), s.rend()) << endl;
    }
    
  • 主文件

    #include <boost/process.hpp>
    #include <boost/asio.hpp>
    #include <boost/process/async.hpp>
    #include <iostream>
    #include <iomanip>
    
    int main() {
        namespace bp = boost::process;
        boost::asio::io_context context;
        bp::async_pipe out(context);
    
        std::string i = "hello\nwo2rld\n";
        bp::child c("./first.exe", bp::std_out > out, bp::std_in < boost::asio::buffer(i), context);
    
        boost::asio::streambuf buffer;
        boost::asio::async_read_until(out, buffer, "2", [&](boost::system::error_code code, std::size_t size) {
            if (code) {
                std::cerr << "Oops: " << code.message() << std::endl;
            } else {
                std::cerr << "received: " << size << " bytes: ";
    
                auto b = buffers_begin(buffer.data()), m = b+size, e = buffers_end(buffer.data());
    
                std::clog << std::quoted(std::string(b, m)) << std::endl;
                std::clog << "Note that we read more bytes: " << std::quoted(std::string(m, e)) << std::endl;
    
                buffer.consume(size);
            }
        });
    
        context.run();
        return c.exit_code();
    }
    

印刷

received: 30 bytes: "reversed: olleh
reversed: dlr2"
Note that we read more bytes: "ow
"

发送动态数据

同步和异步:

#include <boost/process.hpp>
#include <boost/asio.hpp>
#include <boost/process/async.hpp>
#include <iostream>
#include <iomanip>

int main() {
    namespace bp = boost::process;
    boost::asio::io_context context;
    bp::async_pipe out(context), in(context);

    bp::child c("./first.exe", bp::std_out > out, bp::std_in < in, context);

    boost::asio::write(in, boost::asio::buffer("hello ", 6));

    boost::asio::streambuf buffer;
    boost::asio::async_read_until(out, buffer, "2", [&](boost::system::error_code code, std::size_t size) {
        if (code) {
            std::cerr << "Oops: " << code.message() << std::endl;
        } else {
            std::cerr << "received: " << size << " bytes: ";

            auto b = buffers_begin(buffer.data()), m = b+size, e = buffers_end(buffer.data());

            std::clog << std::quoted(std::string(b, m)) << std::endl;
            std::clog << "Note that we read more bytes: " << std::quoted(std::string(m, e)) << std::endl;

            buffer.consume(size);
        }
    });

    boost::asio::async_write(in, boost::asio::buffer("wo2rld\n", 7), [&](boost::system::error_code code, std::size_t size) {
        if (code) {
            std::cerr << "Oops: " << code.message() << std::endl;
        } else {
            std::cerr << "sent: " << size << " bytes: ";
        }
    });

    context.run();
    return c.exit_code();
}

再次打印:

sent: 7 bytes: received: 30 bytes: "reversed: olleh
reversed: dlr2"
Note that we read more bytes: "ow
"
于 2019-09-16T21:30:20.487 回答