11

在这个 Boost.Process 0.5 ( http://www.highscore.de/boost/process0.5/index.html ) 的简单示例中,程序 ( ) 的输出ls正在提供一个流。流工作正常,但与预期相反,程序完成后流不会变得无效(例如流结束)(类似于以前版本的 Boost.Process,例如http://www.highscore.de/boost /process/index.html )

is为了使流(在示例中)在子程序退出后自动失效,我缺少什么?

也许这是我必须在 Boost.Streamsstream中设置的选项file_descriptor

#include <boost/process.hpp> // version 0.5 from http://www.highscore.de/boost/process0.5/process.zip
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <string>
using namespace boost::process;
using namespace boost::process::initializers;
using namespace boost::iostreams;
int main(){
    boost::process::pipe p = create_pipe();
    file_descriptor_sink sink(p.sink, close_handle);
    child c = execute(run_exe("/usr/bin/ls"), bind_stdout(sink));
    file_descriptor_source source(p.source,  close_handle);
    stream<file_descriptor_source> is(source);
    std::string s;
    while(std::getline(is, s)){
        std::cout << "read: " << s << std::endl;
    }
    std::clog << "end" << std::endl; // never reach
}
4

2 回答 2

5

2020 年更新: Boost.Process 现在是 Boost https://www.boost.org/doc/libs/1_74_0/doc/html/process.html的一部分,这个答案可能已经完全过时了。它仅适用于实验版本“0.5” http://www.highscore.de/boost/process0.5/index.html


我与图书馆的作者 Boris Schaeling 进行了私人(实际上是通过 Nabble)交流。在放弃了几种可能性之后,比如 posix/boost.iostreams 中的错误,他给了我对有效代码的轻微修改。基本上,我可以推断出file_descriptor sink必须超出范围(已销毁)才能使流返回 EOF。sink工作代码只是为(在末尾列出)添加了一个特定的范围。我认为这很容易将所有内容封装在一个pistream类中。(我列表中的下一步将是允许输出到进程。)

适用于 Boost 1.48 (Fedora 17)。

#include <boost/process.hpp> // version 0.5
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <string>

using namespace boost::process;
using namespace boost::process::initializers;
using namespace boost::iostreams;

int main() {
    pipe p = create_pipe();
    {
        // note the scope for sink
        file_descriptor_sink sink(p.sink, close_handle);
        /*  child c = */ // not necessary to hold a child object, it seems.
        execute(run_exe("/usr/bin/ls"), bind_stdout(sink));
    }   // note the scope for sink

    file_descriptor_source source(p.source,  close_handle);
    stream<file_descriptor_source> is(source);
    std::string s;
    while(std::getline(is, s)) {
        std::cout << "read: " << s << std::endl;
    }
    std::clog << "end" << std::endl; // never reach
}

编译c(lang)++ -lboost_system -lboost_iostreams

编辑:这似乎也有效,可以避免人为范围,但可能会令人困惑,因为接收器必须是临时的:

    ...
    pipe p = create_pipe();
    execute(run_exe("/usr/bin/ls"), bind_stdout(        
        file_descriptor_sink(p.sink, close_handle)
    ));
    file_descriptor_source source(p.source,  close_handle);
    ...
于 2012-09-18T02:11:33.867 回答
3

这适用于类似 POSIX 的系统:

#include <boost/process.hpp> // version 0.5 from http://www.highscore.de/boost/process0.5/process.zip
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/asio.hpp>
#include <string>

using namespace boost::process;
using namespace boost::process::initializers;
using namespace boost::iostreams;

int main()
{
    boost::asio::io_service io_service;
    int status = 1;
    boost::asio::signal_set set(io_service, SIGCHLD);
    set.async_wait(
        [&status](const boost::system::error_code&, int) { ::wait(&status); }
    );

    boost::process::pipe p = create_pipe();
    file_descriptor_sink sink(p.sink, close_handle);
    child c = execute(run_exe("/bin/ls"), bind_stdout(sink));
    file_descriptor_source source(p.source,  close_handle);
    stream<file_descriptor_source> is(source);
    std::string s;
    while(status && std::getline(is, s))
    {
        std::cout << "read: " << s << std::endl;
    }
    std::clog << "end" << std::endl; // never reach
}

请注意,它将 SIGCHLD 处理为异步设置status。它取自http://www.highscore.de/boost/process0.5/boost_process/tutorial.html#boost_process.tutorial.starting_a_program。此页面还显示了 Windows 的相同做法:

#if defined(BOOST_WINDOWS_API)
    DWORD exit_code;
    boost::asio::windows::object_handle handle(io_service, c.process_handle());
    handle.async_wait(
        [&handle, &exit_code](const boost::system::error_code&)
            { ::GetExitCodeProcess(handle.native(), &exit_code); }
    );
#endif

    io_service.run();
于 2012-09-11T18:59:15.977 回答