我有一些代码使用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的描述符?
答案 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')
来涵盖达尔文的情况。