2017-07-20 35 views
3

boost::childのドキュメントページで、子プロセスの出力の読み方を説明しています。彼らはあなたの子プロセスを実行した後に言う http://www.boost.org/doc/libs/1_64_0/doc/html/boost_process/tutorial.html 、我々はこのループを介して、それを読むことができます: -boost :: childプロセスからすべての行を確実に読み取る方法

bp::ipstream is; //reading pipe-stream 
bp::child c(bp::search_patk("nm"), file, bp::std_out > is); 

//then later 
while (c.running() && std::getline(is, line) && !line.empty()) 
     data.push_back(line); 

私はここに2つの質問があります: -

  1. c.running()戻りfalseの場合、我々は単にループを終了します。そしてその場合、上のストリームisはまだ失われたデータを運ぶかもしれませんか?
    パイプがあれば、デッドロックが発生します - :
  2. 確認プロセスの終了をしながら)(、標準出力を読み、両方を標準エラー出力するための最良の方法は何ですが、デッドロック を作成していないページの格言に警告がありますnmのは、私はおよそnmは、上記終了したりしていない気にすることなくstdoutstderrの両方をキャプチャしたい

を終了した後にお読みしてみてください。

+0

あなたがへリンクのページにさらに少し見下した場合は、標準入力*と*出力の両方のリダイレクトが表示されます。標準出力とエラーの両方をリダイレクトする方法を教えてください。 –

+0

ありがとう、はい私はそれを見た。私は** while ** stdoutとstderrを待つために適切なwhileループが必要です。また、ループの仕組みを知りたい。上記の(1)のようにデータを失うのはなぜですか? –

答えて

2

非同期メソッドを使用しない限り、適切な方法はないと思います。

おそらく、将来のベクトルを手に入れて、何らかの形で実際に行単位で必要とする場合は、string_viewsを使うことができます。

std::future<std::vector<char> > output, error; 

boost::asio::io_service svc; 
bp::child c(bp::search_path("nm"), file, bp::std_out > output, bp::std_err > error, svc); 
svc.run(); 

あなたは、ベクターの上にはistreamを使用することができます前に、あなたがやったように、正確に読み取るには:

#include <boost/process.hpp> 
#include <boost/iostreams/device/array.hpp> 
#include <boost/iostreams/stream_buffer.hpp> 
#include <iostream> 

namespace bp = boost::process; 
namespace bio = boost::iostreams; 
std::string const file = "./a.out"; 

int main() { 
    std::future<std::vector<char> > output, error; 

    boost::asio::io_service svc; 
    bp::child c(bp::search_path("nm"), file, bp::std_out > output, bp::std_err > error, svc); 
    svc.run(); 

    //then later 
    { 
     auto raw = output.get(); 
     std::vector<std::string> data; 
     std::string line; 
     bio::stream_buffer<bio::array_source> sb(raw.data(), raw.size()); 
     std::istream is(&sb); 

     while (std::getline(is, line) && !line.empty()) 
      data.push_back(line); 

     std::cout << data.at(rand()%data.size()) << "\n"; 
    } 

} 
0

私は...これに対処するための最良の方法は、使用して同じ問題でありました非同期入出力。

残念ながら、ブーストドキュメント@http://www.boost.org/doc/libs/master/doc/html/boost_process/extend.html#boost_process.extend.asyncは間違っていました... これはすべてがシンプルに見えますが、バッファのサイズをあらかじめ決めておかなければならないことを示しています。

私の機能は、1つのバッファを送受信します(question/response0のようなやりとりはありません)。私はエラーチェックのためにstderrを使用しています。これはアプリケーションに必要でした。私は実行アプリデコーダ/エンコーダである

using tstring=basic_string<TCHAR>; 

void Run(
    const tstring& exeName; 
    const tstring& args, 
    const std::string& input, 
    std::string& output, 
    std::string& error 
) 
{ 
    using namespace boost; 

    asio::io_service ios; 

    std::vector<char> vOut(128 << 10); 
    auto outBuffer{ asio::buffer(vOut) }; 
    process::async_pipe pipeOut(ios); 

    std::function<void(const system::error_code & ec, std::size_t n)> onStdOut; 
    onStdOut = [&](const system::error_code & ec, size_t n) 
    { 
     output.reserve(output.size() + n); 
     output.insert(output.end(), vOut.begin(), vOut.begin() + n); 
     if (!ec) 
     { 
      asio::async_read(pipeOut, outBuffer, onStdOut); 
     } 
    }; 

    std::vector<char> vErr(128 << 10); 
    auto errBuffer{ asio::buffer(vErr) }; 
    process::async_pipe pipeErr(ios); 
    std::function<void(const system::error_code & ec, std::size_t n)> onStdErr; 
    onStdErr = [&](const system::error_code & ec, size_t n) 
    { 
     error.reserve(error.size() + n); 
     error.insert(error.end(), vErr.begin(), vErr.begin() + n); 
     if (!ec) 
     { 
      asio::async_read(pipeErr, errBuffer, onStdErr); 
     } 
    }; 

    auto inBuffer{ asio::buffer(input) }; 
    process::async_pipe pipeIn(ios); 

    process::child c(
     exeName + _T(" ") + args, 
     process::std_out > pipeOut, 
     process::std_err > pipeErr, 
     process::std_in < pipeIn 
    ); 


    asio::async_write(pipeIn, inBuffer, 
     [&](const system::error_code & ec, std::size_t n) 
     { 
      pipeIn.async_close(); 
     }); 

    asio::async_read(pipeOut, outBuffer, onStdOut); 
    asio::async_read(pipeErr, errBuffer, onStdErr); 

    ios.run(); 
    c.wait(); 
} 

`、私はプロセスにファイル全体を送信し、同時にこのように結果を受け取るなしファイルサイズ制限

;)(c.exit_code」呼び出しありません。

重要

ブースト1.64でバグ修正があり、Windowsにのみ影響します。明らかに、ファイルboost \ process \ detail \ windows \ async_pipeの

です。HPP: 参照:https://github.com/klemens-morgenstern/boost-process/issues/90

行79:

~async_pipe() 
    { 
//fix 
     //if (_sink .native() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_) 
     // ::boost::detail::winapi::CloseHandle(_sink.native()); 
     //if (_source.native() != ::boost::detail::winapi::INVALID_HANDLE_VALUE_) 
     // ::boost::detail::winapi::CloseHandle(_source.native()); 
     boost::system::error_code ec; 
     close(ec); 
//fix 
    } 
関連する問題