是否有一种跨平台方法可以使用 ctypes 可靠地查找 stdout 文件描述符?

发布于 2025-01-01 11:22:13 字数 935 浏览 1 评论 0原文

我有一些代码使用 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 指针(同样stdinstderr)而不假设它使用的是 POSIX 兼容的描述符?

I have some code that uses ctypes to try to determine if the file pointed to by sys.stdout is actually stdout. I know that on any POSIX-compliant system, and even on Windows, it should be safe to assume this is true if sys.stdout.fileno() == 1, so my question is not how to do this in general.

In my code (which is already using ctypes for something unrelated to my question) I carelessly had something like:

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:
    ...

This works perfectly fine on Linux, so I didn't really think about it much. It looked nicer and more readable than hard-coding 1 as the file descriptor. But I found a few days later that my code wasn't working on OSX.

It turns outs OSX's libc doesn't export any symbol called 'stdout'. Instead its stdio.h has stdout defined as:

#define stdout __stdoutp

If I change my code to c_void_p.in_dll(libc, '__stdoutp') my code works as expected, but of course that's OSX-only. Windows, it turns out, has a similar issue (at least if using MSVC).

I will probably just change my code to use 1, but my question still stands, out of curiosity, if there's a cross-platform way to get the stdio pointer (and likewise stdin and stderr) without assuming that it's using the POSIX-compliant descriptor?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ゝ偶尔ゞ 2025-01-08 11:22:13

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

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

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

As so often when it comes to C, if you want compatibility, you'll have to go and look in the relevant standard. Since you mention windows, I guess you're not actually wanting the POSIX standard, but rather the C one.

C99 section 7,19,1 defines stdout to be a macro, and thus not a variable. That means there's no way you can rely on finding it using dlsym (which I assume in_dll uses). The actual expression could just as well be a function call or a fixed address. Perhaps not very likely, but it is possible...

As said in the comments, the fileno function is in turn defined by POSIX, not by C. C has no concept of file descriptors. I think you're better off assuming POSIX and just checking for the value 1, which it specifies.

软糖 2025-01-08 11:22:13

如果您只是想让事情正常工作,而不是严格遵守标准(像我一样),您可以通过编写一个简单的 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') 来覆盖 darwin 的情况。

If you're simply interested in making things work, rather than strict standards adherence (like me), you can find the "real" name of stdout by writing a simple C snippet:

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

Gives you the output:

FILE* mystdout = __stdoutp;

This means that you also need to try ctypes.c_void_p.in_dll(libc, '__stdoutp') to cover the case of darwin.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文