使用 Cython 访问 C 标头幻数/标志

发布于 2024-08-20 12:57:16 字数 657 浏览 4 评论 0原文

我想使用 Cython 访问的一些标准 C 库有大量标志。 Cython 文档声明我必须复制我需要的标头部分。当涉及到函数定义时,这很好。它们通常在各处复制,包括文档。但那些神奇的数字又如何呢?

如果我想调用 mmap,我总是可以找到函数定义并将其粘贴到 .pxd 文件中:

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)

但是调用它需要大量标志,例如 PROT_READMAP_ANONYMOUS 等等。我对此至少有两个问题:

首先,准确查找这些数字的定义位置是一项烦人的工作。事实上,我宁愿编写一个 .c 文件并打印我需要的值。有没有更好的方法来查找给定标志的值,例如 PROT_READ

其次,这些数字有多稳定?提取了我需要的所有值并将它们硬编码到我的 Cython 源代码中后,在不同平台上进行编译的可能性有多大(比如说 PROT_READPROT_EXEC)?

即使答案是没有好的或适当的方法来做到这一点,我也想听听。只要我知道我没有遗漏什么,我总是可以接受某些事情是麻烦的。

Some standard C libraries that I want to access with Cython have a ton of flags. The Cython docs state that I must replicate the parts of the header I need. Which is fine when it comes to functions definitions. They are usually replicated everywhere, docs included. But what about all those magic numbers?

If I want to call mmap, I can always find the function definition and paste it into a .pxd file:

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)

But calling it needs a ton of flags like PROT_READ, MAP_ANONYMOUS and so on. I have at least two problems with this:

Firstly, it is annoying work to hunt down exactly where those numbers are defined. In fact I'd rather write a .c file and printf the values I need. Are there any better way of finding the value of a given flag such as PROT_READ?

Secondly, how stable are these numbers? Having extracted all the values I need and hardcoded them into my Cython source, what are the chances that compiling on a different platform has switched around, let's say PROT_READ and PROT_EXEC?

Even if the answer is that there are no good or proper ways to do it, I'd like to hear it. I can always accept that something is cumbersome as long as I know I'm not missing something.

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

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

发布评论

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

评论(3

江挽川 2024-08-27 12:57:16

要使用 Cython 中的这些常量,您不需要像从 C 中那样准确地弄清楚它们来自哪里或它们是什么。例如,您的 .pxd 文件可以看起来像只要

cdef extern from "foo.h":
    void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
    cdef int PROT_READ
    cdef int MAP_ANONYMOUS
    ...

定义是(直接或间接)从 foo.h 包含,这应该可以正常工作。

To use these constants from Cython, you don't need to figure exactly where they came from or what they are any more than you do from C. For example, your .pxd file can look like

cdef extern from "foo.h":
    void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
    cdef int PROT_READ
    cdef int MAP_ANONYMOUS
    ...

As long as the definitions are (directly or indirectly) included from foo.h, this should work fine.

清风无影 2024-08-27 12:57:16

有几种可能的替代方案:

  1. 使用 Python mmap模块。
    • 简单
    • 仅在存在现有 Python 绑定时才有效

  2. 首先使用 Python mmap 对象,然后将其交给您的 Cython 代码
    • 更简单的打开方式
    • 可能有一些 Python 开销
  3. 使用 的代码生成器ctypeslib
  4. 复制数字即可。

话虽如此,这些数字非常非常稳定。如果它们发生变化,每个使用 mmap 的 C 程序都必须重新编译,因为标头中的标志包含在二进制文件中。

编辑mmap POSIX 的一部分,但是粗略地阅读并没有发现这些标志在所有平台上是否必须具有相同的值。

There are several possible alternatives:

  1. Use the flags from the Python mmap module.
    • simple
    • only works when there are existing Python bindings
  2. Use the Python mmap object in the first place, and hand it over to your Cython code
    • even simpler openening
    • might have some Python overhead
  3. Use the code generator of ctypeslib
    • some docs on how to extract constants
    • needs gccxml
  4. Just copy the numbers.

That being said, the numbers are very, very stable. If they'd change, each and every C program using mmap would have to be recompiled, as the flags from the headers are contained in the binary.

EDIT: mmap is part of POSIX, but a cursory read hasn't revealed whether the flags have to be the same value on all platforms.

情何以堪。 2024-08-27 12:57:16

编写一个文件 foo.c,其内容如下:

#include <sys/mman.h>

然后运行

cpp -dM foo.c | grep -v __ | awk '{if ($3) print $2, "=", $3}' > mman.py

,它将创建一个定义 mman.h 中所有常量的 python 文件,

显然,如果需要,您可以对多个包含执行此操作。

生成的文件可能需要一些清理,但它会让您接近目标。

Write a file foo.c with this as the contents:

#include <sys/mman.h>

Then run

cpp -dM foo.c | grep -v __ | awk '{if ($3) print $2, "=", $3}' > mman.py

which will create a python file that defines all the constants from mman.h

Obviously, you can do that for multiple includes if you want.

The resulting file might need a bit of cleaning up, but it'll get you close.

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