从 std::fstream 获取 FILE\*

新手上路,请多包涵

是否有(跨平台)方法从 C++ std::fstream 获取 C FILE* 句柄?

我问的原因是因为我的 C++ 库接受 fstreams 并且在一个特定的函数中我想使用一个接受 FILE* 的 C 库。

原文由 Bek 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

最简洁的答案是不。

原因是 std::fstream 不需要使用 FILE* 作为其实现的一部分。因此,即使您设法从 std::fstream 对象中提取文件描述符并手动构建一个 FILE 对象,您也会遇到其他问题,因为您现在将有两个缓冲对象写入同一个文件描述符。

真正的问题是为什么要将 std::fstream 对象转换为 FILE*

虽然我不推荐,但您可以尝试查找 funopen()

不幸的是,这 不是 POSIX API(它是 BSD 扩展),因此它的可移植性存在问题。这也可能是为什么我找不到任何人用这样的对象包裹 std::stream 的原因。

 FILE *funopen(
              const void *cookie,
              int    (*readfn )(void *, char *, int),
              int    (*writefn)(void *, const char *, int),
              fpos_t (*seekfn) (void *, fpos_t, int),
              int    (*closefn)(void *)
             );

这允许您构建一个 FILE 对象并指定一些将用于执行实际工作的函数。如果您编写适当的函数,您可以让它们从实际打开文件的 std::fstream 对象中读取。

原文由 Martin York 发布,翻译遵循 CC BY-SA 3.0 许可协议

在 Linux 中执行此操作的另一种方法:

 #include <stdio.h>
#include <cassert>

template<class STREAM>
struct STDIOAdapter
{
    static FILE* yield(STREAM* stream)
    {
        assert(stream != NULL);

        static cookie_io_functions_t Cookies =
        {
            .read  = NULL,
            .write = cookieWrite,
            .seek  = NULL,
            .close = cookieClose
        };

        return fopencookie(stream, "w", Cookies);
    }

    ssize_t static cookieWrite(void* cookie,
        const char* buf,
        size_t size)
    {
        if(cookie == NULL)
            return -1;

        STREAM* writer = static_cast <STREAM*>(cookie);

        writer->write(buf, size);

        return size;
    }

    int static cookieClose(void* cookie)
    {
         return EOF;
    }
}; // STDIOAdapter

用法,例如:

 #include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/bzip2.hpp>
#include <boost/iostreams/device/file.hpp>

using namespace boost::iostreams;

int main()
{
    filtering_ostream out;
    out.push(boost::iostreams::bzip2_compressor());
    out.push(file_sink("my_file.txt"));

    FILE* fp = STDIOAdapter<filtering_ostream>::yield(&out);
    assert(fp > 0);

    fputs("Was up, Man", fp);

    fflush (fp);

    fclose(fp);

    return 1;
}

原文由 Jettatura 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题