是否有一种跨平台的方法可靠地找到带有ctypes的stdout文件描述符?

时间:2012-02-02 20:20:27

标签: python macos posix ctypes darwin

我有一些代码使用ctypes来确定sys.stdout指向的文件是否实际 stdout。我知道在任何符合POSIX标准的系统上,甚至在Windows上,假设sys.stdout.fileno() == 1这是真的应该是安全的,所以我的问题不是如何做到这一点。

在我的代码中(已经将ctypes用于与我的问题无关的东西)我不小心有类似的东西:

libc = ctypes.CDLL(ctypes.util.find_library('c'))
real_stdout = libc.fileno(ctypes.c_void_p.in_dll(libc, 'stdout'))
if sys.stdout.fileno() == real_stdout:
    ...

这在Linux上完全正常,所以我并没有真正考虑它。它比硬编码1作为文件描述符看起来更好,更易读。但几天后我发现我的代码不能用于OSX。

它结束了OSX的libc不会导出任何名为'stdout'的符号。相反,它的stdio.h将stdout定义为:

#define stdout __stdoutp

如果我将代码更改为c_void_p.in_dll(libc, '__stdoutp')我的代码按预期工作,但当然这只是OSX。事实证明,Windows有类似的问题(至少如果使用MSVC)。

我可能只会更改我的代码以使用1,但出于好奇,我的问题仍然存在,如果有一种跨平台方式来获取stdio指针(同样{{1} }}和stdin)没有假设它正在使用符合POSIX的描述符?

2 个答案:

答案 0 :(得分:4)

就C而言,如果你想要兼容性,你必须去看看相关的标准。既然你提到了windows,我猜你实际上并不想要POSIX标准,而是C语言。

C99第7,19,1节将stdout定义为宏,因此不是变量。这意味着你无法依靠使用dlsym(我假设使用in_dll)来依赖它。实际表达式也可以是函数调用或固定地址。也许不太可能,但有可能......

如评论中所述,fileno函数依次由POSIX定义,而不是由C定义.C没有文件描述符的概念。我认为你最好假设POSIX并且只检查它指定的值1。

答案 1 :(得分:3)

如果您只是对制作工作感兴趣,而不是严格的标准依从性(像我一样),您可以找到真实的"通过编写一个简单的C片段来标识stdout:

echo -e '#include <stdio.h>\nFILE* mystdout = stdout;' > test.c
cpp test.c | tail

给你输出:

FILE* mystdout = __stdoutp;

这意味着您还需要尝试ctypes.c_void_p.in_dll(libc, '__stdoutp')来涵盖达尔文的情况。