我正在 Windows 上使用一些 C++ 来启动 python.exe (2.7) 并使用 stdin、stdout 和 stderr 与之交互。我正在使用 Visual Studio 2015、Boost 1.59 和 Boost Process 0.5。
我通过设置命令行来成功启动 python.exe,例如“python -c”print 'hello world'”,并且标准输出捕获“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 启动到交互模式,就像我从命令行执行“python.exe”一样。
该代码在这里:
#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;
}
当我运行第二个示例时,python 将暂时运行,然后关闭。
这个程序的一些背景。我想创建一个 Python 记录器,它逐行读取 Python 文件,并逐行执行它,就好像它是在解释器中编写的一样。因此,会有如下代码:
pyChild.waitForPrompt(); // Waits for >>>, >>?, ..., etc.
pyChild.write("print 'hello world'); // >>> print 'hello world'
std::cout << pyChild.readLine(); // hello world
我与 boost 无关,我尝试过其他选项,例如 Poco 和MSDN Windows 示例,但没有成功。
当然,在正确传输标准输出/标准错误后,标准输入也将正常工作。我也试图让它发挥作用,但失败了。
提前致谢!