Encontré this question que pregunta cómo leer la entrada de forma asíncrona, pero solo funcionará con los descriptores de flujo POSIX, que no funcionarán en Windows. Entonces, encontré this tutorial que muestra que en lugar de usar un descriptor de flujo POSIX puedo usar un boost::asio::windows::stream_handle
.¿Cómo leer de forma asíncrona la entrada desde la línea de comando usando boost asio en Windows?
Siguiendo los dos ejemplos, obtuve el siguiente código. Cuando lo ejecuto, no puedo escribir nada en el símbolo del sistema, ya que el programa termina inmediatamente. Me gustaría capturar cualquier entrada del usuario, posiblemente en un std::string
, mientras que permite que se ejecute otra lógica dentro de mi programa (es decir, realizar E/S asincrónicas desde una consola de Windows).
Esencialmente, estoy tratando de evitar el bloqueo de mi programa cuando intenta leer desde stdin
. No sé si esto es posible en Windows, ya que también encontré this post que detalla los problemas que otro usuario encontró al intentar hacer lo mismo.
#define _WIN32_WINNT 0x0501
#define INPUT_BUFFER_LENGTH 512
#include <cstdio>
#include <iostream>
#define BOOST_THREAD_USE_LIB // For MinGW 4.5 - (https://svn.boost.org/trac/boost/ticket/4878)
#include <boost/bind.hpp>
#include <boost/asio.hpp>
class Example {
public:
Example(boost::asio::io_service& io_service)
: input_buffer(INPUT_BUFFER_LENGTH), input_handle(io_service)
{
// Read a line of input.
boost::asio::async_read_until(input_handle, input_buffer, "\r\n",
boost::bind(&Example::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void handle_read(const boost::system::error_code& error, std::size_t length);
void handle_write(const boost::system::error_code& error);
private:
boost::asio::streambuf input_buffer;
boost::asio::windows::stream_handle input_handle;
};
void Example::handle_read(const boost::system::error_code& error, std::size_t length)
{
if (!error)
{
// Remove newline from input.
input_buffer.consume(1);
input_buffer.commit(length - 1);
std::istream is(&input_buffer);
std::string s;
is >> s;
std::cout << s << std::endl;
boost::asio::async_read_until(input_handle, input_buffer, "\r\n",
boost::bind(&Example::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
else if(error == boost::asio::error::not_found)
{
std::cout << "Did not receive ending character!" << std::endl;
}
}
void Example::handle_write(const boost::system::error_code& error)
{
if (!error)
{
// Read a line of input.
boost::asio::async_read_until(input_handle, input_buffer, "\r\n",
boost::bind(&Example::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
}
int main(int argc, char ** argv)
{
try {
boost::asio::io_service io_service;
Example obj(io_service);
io_service.run();
} catch(std::exception & e)
{
std::cout << e.what() << std::endl;
}
std::cout << "Program has ended" << std::endl;
getchar();
return 0;
}
No soy usuario de Windows, pero ¿no usa \ r \ n como un nuevo indicador de línea? –
Sí, pero ¿eso evitará que funcione, ya que \ n todavía está en la secuencia de nueva línea? Cambié la cadena delímetro a "\ r \ n", el mismo resultado. – nickb
donde invocar io_service :: run()? –