读取阻塞进程的输出
Reading output of blocking process
我有一些简单的应用程序:
//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 执行回调函数。您对让它按预期工作有什么建议吗?
在这种情况下,我认为您不需要做任何事情(std::cin
读取可能会失败):
#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);
这些都有效(参见 live)。
更复杂
如果您实际上需要提供输入以获得输出怎么办?或者您需要根据输出提供输入?那么评论者是对的:将管道附加到 std_in(或异步写入缓冲区)。
发送固定缓冲区
first.cpp
#include <iostream>
int main() {
using namespace std;
string s;
while (cin >> s)
cout << "reversed: " << string(s.rbegin(), s.rend()) << endl;
}
main.cpp
#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
"
我有一些简单的应用程序:
//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 执行回调函数。您对让它按预期工作有什么建议吗?
在这种情况下,我认为您不需要做任何事情(std::cin
读取可能会失败):
#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);
这些都有效(参见 live)。
更复杂
如果您实际上需要提供输入以获得输出怎么办?或者您需要根据输出提供输入?那么评论者是对的:将管道附加到 std_in(或异步写入缓冲区)。
发送固定缓冲区
first.cpp
#include <iostream> int main() { using namespace std; string s; while (cin >> s) cout << "reversed: " << string(s.rbegin(), s.rend()) << endl; }
main.cpp
#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
"