Is there a (cross-platform) way to get a C FILE* handle from a C++ std::fstream ?
The reason I ask is because my C++ library accepts fstreams and in one particular function I'd like to use a C library that accepts a FILE*.
Is there a (cross-platform) way to get a C FILE* handle from a C++ std::fstream ?
The reason I ask is because my C++ library accepts fstreams and in one particular function I'd like to use a C library that accepts a FILE*.
In a single-threaded POSIX application you can easily get the fd number in a portable way:
This method breaks in a multi-threaded application if this code races with other threads opening file descriptors.
yet another way to do this in Linux:
Usage, for example:
Well, you can get the file descriptor - I forget whether the method is fd() or getfd(). The implementations I've used provide such methods, but the language standard doesn't require them, I believe - the standard shouldn't care whether your platform uses fd's for files.
From that, you can use fdopen(fd, mode) to get a FILE*.
However, I think that the mechanisms the standard requires for synching STDIN/cin, STDOUT/cout and STDERR/cerr don't have to be visible to you. So if you're using both the fstream and FILE*, buffering may mess you up.
Also, if either the fstream OR the FILE closes, they'll probably close the underlying fd, so you need to make sure you flush BOTH before closing EITHER.
Please, look at this library
MDS utils
It solves the problem, because allows to treat a C FILE* as a C++ stream. It uses Boost C++ libraries. You have to use Doxygen to view the documentation.
There is a way to get file descriptor from
fstream
and then convert it toFILE*
(viafdopen
). Personally I don't see any need inFILE*
, but with file descriptor you may do many interesting things such as redirecting (dup2
).Solution:
The last string works for libstdc++. If you are using some other library you will need to reverse-engineer it a bit.
This trick is dirty and will expose all private and public members of fstream. If you would like to use it in your production code I suggest you to create separate
.cpp
and.h
with single functionint getFdFromFstream(std::basic_ios<char>& fstr);
. Header file must not include fstream.The short answer is no.
The reason, is because the
std::fstream
is not required to use aFILE*
as part of its implementation. So even if you manage to extract file descriptor from thestd::fstream
object and manually build a FILE object, then you will have other problems because you will now have two buffered objects writing to the same file descriptor.The real question is why do you want to convert the
std::fstream
object into aFILE*
?Though I don't recommend it, you could try looking up
funopen()
.Unfortunately, this is not a POSIX API (it's a BSD extension) so its portability is in question. Which is also probably why I can't find anybody that has wrapped a
std::stream
with an object like this.This allows you to build a
FILE
object and specify some functions that will be used to do the actual work. If you write appropriate functions you can get them to read from thestd::fstream
object that actually has the file open.