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*.
There isn't a standardized way. I assume this is because the C++ standardization group didn't want to assume that a file handle can be represented as a fd.
Most platforms do seem to provide some non-standard way to do this.
http://www.ginac.de/~kreckel/fileno/ provides a good writeup of the situation and provides code that hides all the platform specific grossness, at least for GCC. Given how gross this is just on GCC, I think I'd avoid doing this all together if possible.
ORIGINAL:
(Probably not cross platform, but simple)
Simplifiying the hack in http://www.ginac.de/~kreckel/fileno/ (dvorak answer), and looking at this gcc extension http://gcc.gnu.org/onlinedocs/gcc-4.6.2/libstdc++/api/a00069.html#a59f78806603c619eafcd4537c920f859, I have this solution that works on
GCC
(4.8 at least) andclang
(3.3 at least)and can be used this,
Limitations: (comments are welcomed)
I find that it is important to
fflush
afterfprintf
printing tostd::ofstream
, otherwise the "sample2" appears before "sample1" in the example above. I don't know if there is a better workaround for that than usingfflush
. Notablyofs << flush
doesn't help.Cannot extract FILE* from
std::stringstream
, I don't even know if it is possible. (see below for an update).I still don't know how to extract C's
stderr
fromstd::cerr
etc., for example to use infprintf(stderr, "sample")
, in an hypothetical code like thisfprintf(cfile(std::cerr), "sample")
.Regarding the last limitation, the only workaround I found is to add these overloads:
Attempt to handle
iostringstream
It is possible to read with
fscanf
fromistream
usingfmemopen
, but that requires a lot of book keeping and updating the input position of the stream after each read, if one wants to combine C-reads and C++-reads. I wasn't able to convert this into acfile
function like above. (Maybe acfile
class that keeps updating after each read is the way to go).