通过stdin和ostream将数据发送到程序.(C++)

Dre*_*rew 10 c++ popen filehandle ostream

我想将我的C++程序中的数据发送到外部管道,如下所示:

FILE* file = popen("my_prog -opt | other_prog", "w");
std::ostream fileStream = some_function(file);
fileStream << "some data";
Run Code Online (Sandbox Code Playgroud)

我知道没有简单的,跨平台的方式来做第二行,但有没有办法用其他东西来完成同样的事情popen?我不需要使用popen,但我确实需要使用ostream.它需要使用clanggcc至少进行编译,但最好能与任何编译器一起使用.我也可以改变我处理管道的方式,但是我没有源my_progother_prog.

Die*_*ühl 8

使用FILE*作为基础目标创建流缓冲区是直接的,并std::ostream使用这样的流缓冲区创建相应的.它大致看起来像这样:

#include <stdio.h>
#include <streambuf>
#include <ostream>

class stdiobuf
    : public std::streambuf {
    enum { bufsize = 2048 };
    char buffer[bufsize];
    FILE* fp;
    int   (*close)(FILE*);
    int overflow(int c) {
        if (c != std::char_traits<char>::eof()) {
            *this->pptr() = std::char_traits<char>::to_char_type(c);
            this->pbump(1);
        }
        return this->sync()
            ? std::char_traits<char>::eof()
            : std::char_traits<char>::not_eof(c);
    }
    int sync() {
        std::streamsize size(this->pptr() - this->pbase());
        std::streamsize done(this->fp? fwrite(this->pbase(), 1, size, this->fp): 0);
        this->setp(this->pbase(), this->epptr());
        return size == done? 0: -1;
    }
public:
    stdiobuf(FILE* fp, int(*close)(FILE*) = fclose)
        : fp(fp)
        , close(close) {
        this->setp(this->buffer, this->buffer + (this->fp? bufsize - 1: 0));
    }
    ~stdiobuf() {
        this->sync();
        this->fp && this->close(this->fp);
    }
};
class opipestream
    : private virtual stdiobuf
    , public std::ostream {
public:
    opipestream(std::string const& pipe)
        : stdiobuf(popen(pipe.c_str(), "w"), pclose)
        , std::ios(static_cast<std::streambuf*>(this))
        , std::ostream(static_cast<std::streambuf*>(this)) {
    }
};

int main()
{
    opipestream out("/usr/bin/sed -e 's/^/xxxx /'");
    out << "Hello\n";
    out << "world\n";
}
Run Code Online (Sandbox Code Playgroud)

基本思想是您可以通过实现流缓冲区来创建新流.上面的实现应该相当完整.虽然最可能出现错误的情况是管道已关闭且没有太多可以做的事情,但是可以改进不完整缓冲区时的错误处理.