https://www.boost.org/library/latest/process
https://www.boost.org/library/latest/asio
boost asio has two kind of pipe:
asio::readable_pipe is a pipe end that has
defined methods .read_some and .async_read_some,
it does not define write methods.
asio::writable_pipe is a pipe end that has
defined methods .write_some and .async_write_some,
it does not define read methods.
So we can read from the asio::readable_pipe
object, but we can not write to it ;
and write to
the asio::writable_pipe object, but we can not
read from it.
We can connect a readable-pipe and a writable-pipe with asio::connect_pipe :
asio::connect_pipe(readable_pipe, writable_pipe);
Pipe game: a pipe c++ example.
Filename: jamroot
project : default-build <cxxstd>26 ; exe bpp-1 : bpp-1.cpp ;
The write-pipe end must be closed after writing and before reading read-pipe end.
Filename: bpp-1.cpp
#include <boost/asio.hpp> #include <iostream> int main() { try { boost::asio::thread_pool pool{32}; boost::asio::readable_pipe rp{pool.get_executor()}; boost::asio::writable_pipe wp{pool.get_executor()}; boost::asio::connect_pipe(rp, wp); boost::system::error_code ec; boost::asio::write(wp, boost::asio::buffer("Hello, c++ world."), ec); // The write-pipe end must be closed after writing and before reading read-pipe end. wp.close(); if (ec) throw std::system_error{ec, "error: write pipe"}; std::string received; boost::asio::read(rp, boost::asio::dynamic_buffer(received), ec); if (ec && ec != boost::asio::error::eof) throw std::system_error{ec, "error: read pipe"}; std::cout << "Received: " << received << std::endl; } catch (const std::system_error & e) { std::cerr << "====>\n" << "e.what(): " << e.what() << '\n' << "e.code(): " << e.code() << '\n' ; } }
> b2 ...found 10 targets... > ./bin/gcc-15/debug/cxxstd-26-iso/bpp-1 Received: Hello, c++ world.
boost::process v2 is default since boost 1.89.
boost::process::process proc{ executor, "/path/prog", {param1, ...}, boost::process::process_stdio{ .in = ???, .out = ???, .err = ??? } };
Filename: jamroot
project : default-build <cxxstd>26 ; lib boost_process ; lib boost_filesystem ; exe bpp : bpp.cpp : <library>boost_process <library>boost_filesystem ;
Filename: bpp.cpp
#include <boost/process.hpp> #include <boost/asio.hpp> #include <iostream> namespace bpp = boost::process; namespace asio = boost::asio; // not hpp int main() { try { asio::thread_pool pool{32}; asio::readable_pipe rp{pool.get_executor()}; asio::writable_pipe wp{pool.get_executor()}; asio::connect_pipe(rp, wp); bpp::process proc{ pool.get_executor(), bpp::environment::find_executable("ugrep"), { "-rIni", R"(\.hpp)", "." }, bpp::process_stdio{ .out = wp } }; if (proc.wait() != 0) throw std::runtime_error{"proc error"}; wp.close(); std::string result; bpp::error_code ec; asio::read(rp, asio::dynamic_buffer(result), ec); if (ec && ec != asio::error::eof) throw std::system_error{ec, "read pipe error"}; std::cout << "Result:\n" << result << std::endl; } catch (const std::exception & e) { std::cout << "====>\n" << e.what() << std::endl; } }
The example will run ugrep -rIni
'\.hpp' .
and save result to c++ std::string result.
.out is assigned with a writable-pipe.
Filename: bpp.cpp
#include <boost/process.hpp> #include <boost/asio.hpp> #include <iostream> namespace bpp = boost::process; namespace asio = boost::asio; // not hpp int main() { try { asio::thread_pool pool{32}; asio::readable_pipe rp{pool.get_executor()}; bpp::process proc{ pool.get_executor(), bpp::environment::find_executable("ugrep"), { "-rIni", R"(\.hpp)", "." }, bpp::process_stdio{ .out = rp } }; std::string result; boost::system::error_code ec; asio::read(rp, asio::dynamic_buffer(result), ec); if (ec && ec != asio::error::eof) throw std::system_error{ec, "error: read pipe"}; std::cout << "Result:\n" << result << std::endl; } catch (const std::exception & e) { std::cout << "====>\n" << e.what() << std::endl; } }
In this example, because .out is
assigned with a readable-pipe,
a writable-pipe will be created internally
and connected to the readable-pipe.
Using boost::process in asynchrous and awaitable asio c++ code.
#include <boost/process.hpp> #include <boost/asio.hpp> #include <iostream> namespace app { class program: virtual public std::enable_shared_from_this<app::program> { private: std::shared_ptr<boost::process::process> __proc; std::shared_ptr<boost::asio::readable_pipe> __rp; public: boost::asio::awaitable<void> start() { co_await this->init(); co_await this->run_program(); co_await this->get_output(); } protected: boost::asio::awaitable<void> init() { __rp = std::make_shared<boost::asio::readable_pipe>( co_await boost::asio::this_coro::executor ); __proc = std::shared_ptr<boost::process::process>{ new boost::process::process{ co_await boost::asio::this_coro::executor, boost::process::environment::find_executable("falkon"), std::initializer_list<boost::string_view>{ "http://cppfx.i2p" }, boost::process::process_stdio{ .out = *__rp } } }; } boost::asio::awaitable<void> run_program() { auto [ec, status] = co_await __proc->async_wait( boost::asio::as_tuple ); boost::process::check_exit_code(ec, __proc->native_exit_code()); if (ec || status != 0) throw std::system_error{ec, "wait proc error"}; // else std::cout << "OK" << std::endl; } boost::asio::awaitable<void> get_output() { std::string result; auto [ec, bytes] = co_await boost::asio::async_read( *__rp, boost::asio::dynamic_buffer(result), boost::asio::as_tuple ); if (ec && ec != boost::asio::error::eof) throw std::system_error{ec, "read pipe error"}; if (result.empty()) std::cout << "No data." << std::endl; else std::cout << "Result: " << result << std::endl; } }; } int main() { try { boost::asio::thread_pool pool{32}; boost::asio::co_spawn( pool.get_executor(), std::bind( &app::program::start, std::make_shared<app::program>() ), [] (std::exception_ptr eptr) { if (eptr) std::rethrow_exception(eptr); } ); pool.join(); } catch (const std::exception & e) { std::cout << "====>\n" << e.what() << std::endl; } }
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
Tue Dec 30 05:43:03 AM UTC 2025
//////////////////////////////////////////////////////////////////////
Powered by - B2 Build | boost quickbook | I2Pd
====
cppfxjjm5bgqx2cepvisfcy4zz4ystzxxh36mtuvqm2jp5g6rb7a.b32.i2p