UPDATE: see @Jettatura, what I consider the best answer is https://stackoverflow.com/a/312412/123124/. (Linux only).
ORIGINAL:
(Maybe not a cross platform, but simple)
Hacking simplification http://www.ginac.de/~kreckel/fileno/ (dvorak answer) and viewing 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 (at least 4.8) and clang (at least 3.3)
#include<fstream> #include<ext/stdio_filebuf.h> typedef std::basic_ofstream<char>::__filebuf_type buffer_t; typedef __gnu_cxx::stdio_filebuf<char> io_buffer_t; FILE* cfile_impl(buffer_t* const fb){ return (static_cast<io_buffer_t* const>(fb))->file(); //type std::__c_file } FILE* cfile(std::ofstream const& ofs){return cfile_impl(ofs.rdbuf());} FILE* cfile(std::ifstream const& ifs){return cfile_impl(ifs.rdbuf());}
and you can use it,
int main(){ std::ofstream ofs("file.txt"); fprintf(cfile(ofs), "sample1"); fflush(cfile(ofs));
Limitations: (comments are welcome)
I believe that after fprintf printing before std::ofstream is important fflush , otherwise "sample2" will appear before "sample1" in the above example. I don't know if there is a better solution for this than using fflush . In particular, ofs << flush does not help.
It is not possible to extract the * file from std::stringstream , I don’t even know if this is possible. (see below for an update).
I still don't know how to extract C stderr from std::cerr , etc., for example, for use in fprintf(stderr, "sample") , in hypothetical code like this fprintf(cfile(std::cerr), "sample") .
Regarding the last limitation, the only workaround I found was to add these overloads:
FILE* cfile(std::ostream const& os){ if(std::ofstream const* ofsP = dynamic_cast<std::ofstream const*>(&os)) return cfile(*ofsP); if(&os == &std::cerr) return stderr; if(&os == &std::cout) return stdout; if(&os == &std::clog) return stderr; if(dynamic_cast<std::ostringstream const*>(&os) != 0){ throw std::runtime_error("don't know cannot extract FILE pointer from std::ostringstream"); } return 0;
Attempted to contact iostringstream
With fmemopen you can read using fscanf from istream , but this requires a lot of accounting and updating the input position of the stream after each read, if you want to combine C-reads and C ++ - reads. I could not convert this to a cfile function as shown above. (Maybe the cfile class, which keeps updating after every read, is the way to go).
// hack to access the protected member of istreambuf that know the current position char* access_gptr(std::basic_streambuf<char, std::char_traits<char>>& bs){ struct access_class : std::basic_streambuf<char, std::char_traits<char>>{ char* access_gptr() const{return this->gptr();} }; return ((access_class*)(&bs))->access_gptr(); } int main(){ std::istringstream iss("11 22 33"); // read the C++ way int j1; iss >> j1; std::cout << j1 << std::endl; // read the C way float j2; char* buf = access_gptr(*iss.rdbuf()); // get current position size_t buf_size = iss.rdbuf()->in_avail(); // get remaining characters FILE* file = fmemopen(buf, buf_size, "r"); // open buffer memory as FILE* fscanf(file, "%f", &j2); // finally! iss.rdbuf()->pubseekoff(ftell(file), iss.cur, iss.in); // update input stream position from current FILE position. std::cout << "j2 = " << j2 << std::endl; // read again the C++ way int j3; iss >> j3; std::cout << "j3 = " << j3 << std::endl; }