1

私は、python.exe (2.7) を起動し、stdin、stdout、および stderr を使用して操作できるようにする Windows でいくつかの C++ を使用しています。Visual Studio 2015、Boost 1.59、および Boost Process 0.5 を使用しています。

「python -c "p​​rint 'hello world'」などのコマンド ラインを設定して python.exe を起動すると、stdout で「hello world」がキャプチャされます。

そのコードは次のとおりです。

#include <boost/process.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <iostream>
#include <fstream>

namespace bp = boost::process;
namespace io = boost::iostreams;
using namespace bp;
using namespace bp::initializers;

bp::pipe create_async_pipe(std::string desc)
{
#if defined(BOOST_WINDOWS_API)
    std::string name = "\\\\.\\pipe\\boost_process_async_io\\" + desc;
    HANDLE handle1 = ::CreateNamedPipeA(name.c_str(), PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, NULL);
    HANDLE handle2 = ::CreateFileA(name.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    return make_pipe(handle1, handle2);
#elif defined(BOOST_POSIX_API)
    return create_pipe();
#endif
}

int main()
{
    bp::pipe pIn = create_async_pipe("stdout");
    //bp::pipe pOut = create_async_pipe("stdin");
    {
        //io::file_descriptor_sink stdout_sink("C:\\WA\\output.txt");
        io::file_descriptor_sink stdout_sink(pIn.sink, io::close_handle);
        //io::file_descriptor_source stdin_source(pOut.source, io::close_handle);
        bp::child c = execute(
            run_exe("C:\\Python27\\python.exe"),
            set_cmd_line(L"python -c \"print 'hello world'\""),
            bind_stdout(stdout_sink),
            bind_stderr(stdout_sink)//,
            //bind_stdin(stdin_source)
            );
    }

    io::file_descriptor_source stdout_source(pIn.source, io::close_handle);
    //io::file_descriptor_sink stdin_sink(pOut.sink, io::close_handle);

    io::stream<io::file_descriptor_source> is(stdout_source);
    //io::stream<io::file_descriptor_sink> os(stdin_sink);

    //os << "print 'hello world'\r\nexit()\r\n";

    std::string output;
    std::getline(is, output);
    std::cout << output << std::endl;   
}

set_cmd_line() を削除するか、文字列を L"python" に変更すると、コマンド ラインから "python.exe" を実行した場合と同様に、Python が対話モードで起動することが期待されます。

そのコードはここにあります:

#include <boost/process.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <iostream>
#include <fstream>

namespace bp = boost::process;
namespace io = boost::iostreams;
using namespace bp;
using namespace bp::initializers;

bp::pipe create_async_pipe(std::string desc)
{
#if defined(BOOST_WINDOWS_API)
    std::string name = "\\\\.\\pipe\\boost_process_async_io\\" + desc;
    HANDLE handle1 = ::CreateNamedPipeA(name.c_str(), PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, NULL);
    HANDLE handle2 = ::CreateFileA(name.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    return make_pipe(handle1, handle2);
#elif defined(BOOST_POSIX_API)
    return create_pipe();
#endif
}

int main()
{
    bp::pipe pIn = create_async_pipe("stdout");
    //bp::pipe pOut = create_async_pipe("stdin");
    {
        //io::file_descriptor_sink stdout_sink("C:\\WA\\output.txt");
        io::file_descriptor_sink stdout_sink(pIn.sink, io::close_handle);
        //io::file_descriptor_source stdin_source(pOut.source, io::close_handle);
        bp::child c = execute(
            run_exe("C:\\Python27\\python.exe"),
            **//set_cmd_line(L"python -c \"print 'hello world'\""),**
            bind_stdout(stdout_sink),
            bind_stderr(stdout_sink)//,
            //bind_stdin(stdin_source)
            );
    }

    io::file_descriptor_source stdout_source(pIn.source, io::close_handle);
    //io::file_descriptor_sink stdin_sink(pOut.sink, io::close_handle);

    io::stream<io::file_descriptor_source> is(stdout_source);
    //io::stream<io::file_descriptor_sink> os(stdin_sink);

    //os << "print 'hello world'\r\nexit()\r\n";

    std::string output;
    std::getline(is, output);
    std::cout << output << std::endl;   
}

2 番目の例を実行すると、python が一瞬だけ実行され、その後終了します。

このプログラムの背景。Python ファイルを 1 行ずつ読み取り、インタープリターで記述されているかのように 1 行ずつ実行する Python ロガーを作成したいと考えています。したがって、次のようなコードになります。

pyChild.waitForPrompt();             // Waits for >>>, >>?, ..., etc.
pyChild.write("print 'hello world'); // >>> print 'hello world'
std::cout << pyChild.readLine();     // hello world

私はブーストに縛られていません。Poco やMSDN Windows の例 hereなどの他のオプションを試しましたが、成功しませんでした。

もちろん、stdout/stderr を正しくパイプ処理した後は、stdin も機能するようになります。私もそれを機能させようとしましたが、失敗しました。

前もって感謝します!

4

1 に答える 1