8
我將一些代碼移植到Darwin OS X中,並且作爲更改的一部分,我們從gcc轉到clang編譯器。如何從std :: basic_ios獲取文件描述符以在OS X上進行叮噹聲?
在代碼中,有一個從2005年開始的功能,並在互聯網上發佈了幾個地方。它爲幾個不同的GCC版本提供了功能,除了它提供的最後版本,v3.4.0或更高版本外,我已經編輯了所有版本。代碼取決於兩個GCC特定類:__gnu_cxx::stdio_filebuf
和__gnu_cxx::stdio_sync_filebuf
。
//! Similar to fileno(3), but taking a C++ stream as argument instead of a
//! FILE*. Note that there is no way for the library to track what you do with
//! the descriptor, so be careful.
//! \return The integer file descriptor associated with the stream, or -1 if
//! that stream is invalid. In the latter case, for the sake of keeping the
//! code as similar to fileno(3), errno is set to EBADF.
//! \see The <A HREF="http://www.ginac.de/~kreckel/fileno/">upstream page at
//! http://www.ginac.de/~kreckel/fileno/</A> of this code provides more
//! detailed information.
template <typename charT, typename traits>
inline int
fileno_hack(const std::basic_ios<charT, traits>& stream)
{
// Some C++ runtime libraries shipped with ancient GCC, Sun Pro,
// Sun WS/Forte 5/6, Compaq C++ supported non-standard file descriptor
// access basic_filebuf<>::fd(). Alas, starting from GCC 3.1, the GNU C++
// runtime removes all non-standard std::filebuf methods and provides an
// extension template class __gnu_cxx::stdio_filebuf on all systems where
// that appears to make sense (i.e. at least all Unix systems). Starting
// from GCC 3.4, there is an __gnu_cxx::stdio_sync_filebuf, in addition.
// Sorry, darling, I must get brutal to fetch the darn file descriptor!
// Please complain to your compiler/libstdc++ vendor...
#if defined(__GLIBCXX__) || defined(__GLIBCPP__)
// OK, stop reading here, because it's getting obscene. Cross fingers!
# if defined(__GLIBCXX__) // >= GCC 3.4.0
// This applies to cin, cout and cerr when not synced with stdio:
typedef __gnu_cxx::stdio_filebuf<charT, traits> unix_filebuf_t;
unix_filebuf_t* fbuf = dynamic_cast<unix_filebuf_t*>(stream.rdbuf());
if (fbuf != NULL) {
return fbuf->fd();
}
// This applies to filestreams:
typedef std::basic_filebuf<charT, traits> filebuf_t;
filebuf_t* bbuf = dynamic_cast<filebuf_t*>(stream.rdbuf());
if (bbuf != NULL) {
// This subclass is only there for accessing the FILE*. Ouuwww, sucks!
struct my_filebuf : public std::basic_filebuf<charT, traits> {
int fd() { return this->_M_file.fd(); }
};
return static_cast<my_filebuf*>(bbuf)->fd();
}
// This applies to cin, cout and cerr when synced with stdio:
typedef __gnu_cxx::stdio_sync_filebuf<charT, traits> sync_filebuf_t;
sync_filebuf_t* sbuf = dynamic_cast<sync_filebuf_t*>(stream.rdbuf());
if (sbuf != NULL) {
return fileno(sbuf->file());
}
# endif
#else
# error "Does anybody know how to fetch the bloody file descriptor?"
return stream.rdbuf()->fd(); // Maybe a good start?
#endif
errno = EBADF;
return -1;
}
的問題是,對鐺5.1 OS X小牛隊,這將是對計算的std::basic_ios
文件描述符的方式嗎?
我可以告訴你,在使用C++運行時很可能是LLVM項目[libC++](http://libcxx.llvm.org/index.html),並且它的'basic_filebuf'類似乎包裝stdio'FILE'而不是直接使用OS級文件描述符。但是我沒有辦法從'filebuf'中提取'FILE'或者從已經打開的'FILE'中創建一個'filebuf'。也許有人比我更聰明。 – zwol
你有周圍嗎?你做了什麼? – Paulo1205
@ Paulo1205問題從未解決,我的調用代碼只處理'return -1'和'errno == EBADF'的情況。 – WilliamKF