gpt4 book ai didi

c++ - 如何从 std::basic_ios 为 OS X 上的 clang 获取文件描述符?

转载 作者:可可西里 更新时间:2023-11-01 16:42:28 27 4
gpt4 key购买 nike

我正在将一些代码移植到 Darwin OS X,作为更改的一部分,我们从 gcc 转到 clang 编译器。

代码中有一个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;
}

问题是,对于 OS X Mavericks 上的 clang 5.1,计算 std::basic_ios 的文件描述符的方法是什么?

最佳答案

如果您不介意在私有(private)实现细节中弄脏手,以下代码有效:

#include <iostream>
#include <fstream>

// Generate a static data member of type Tag::type in which to store
// the address of a private member. It is crucial that Tag does not
// depend on the /value/ of the the stored address in any way so that
// we can access it from ordinary code without directly touching
// private data.
template < class Tag >
struct stowed
{
static typename Tag::type value;
};

template < class Tag >
typename Tag::type stowed< Tag >::value;

// Generate a static data member whose constructor initializes
// stowed< Tag >::value. This type will only be named in an explicit
// instantiation, where it is legal to pass the address of a private
// member.
template < class Tag, typename Tag::type x >
struct stow_private
{
stow_private() { stowed< Tag >::value = x; }
static stow_private instance;
};
template < class Tag, typename Tag::type x >
stow_private< Tag, x > stow_private< Tag, x >::instance;

struct filebuf_file { typedef FILE*( std::filebuf::*type ); };
template struct stow_private< filebuf_file, &std::filebuf::__file_ >;

FILE* c_file( std::filebuf& fb )
{
return fb.*stowed< filebuf_file >::value;
}

int main(int argc, const char * argv[])
{
std::ofstream fs("test.txt");
FILE* file = c_file(*fs.rdbuf());
std::cout << file->_file << "\n";
return 0;
}

关于c++ - 如何从 std::basic_ios 为 OS X 上的 clang 获取文件描述符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22624503/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com