用Cython访问C头文件中的魔法数字/标志

4 投票
3 回答
1025 浏览
提问于 2025-04-15 18:55

我想用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文件,然后用printf打印出我需要的值。有没有更好的方法来找到某个标志的值,比如PROT_READ

其次,这些数字有多稳定?假设我提取了所有需要的值,并把它们硬编码到我的Cython源代码里,那么在不同的平台上编译时,PROT_READPROT_EXEC的值会不会互换?

即使答案是没有好的或合适的方法,我也想听听。我总是能接受某些事情很麻烦,只要我知道自己没有漏掉什么。

3 个回答

1

创建一个名为 foo.c 的文件,里面写入以下内容:

#include <sys/mman.h>

然后运行下面的命令:

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

这个命令会生成一个 Python 文件,里面定义了 mman.h 中的所有常量。

显然,如果你想的话,可以对多个包含文件这样操作。

生成的文件可能需要稍微整理一下,但基本上能满足你的需求。

2

这里有几种可能的替代方案:

  1. 使用Python的mmap模块中的标志。
    • 简单
    • 仅在已有Python绑定的情况下有效
  2. 直接使用Python的mmap对象,然后把它交给你的Cython代码。
    • 打开方式更简单
    • 可能会有一些Python的额外开销
  3. 使用ctypeslib的代码生成器。
  4. 直接复制这些数字。

不过,这些数字是非常非常稳定的。如果它们发生变化,所有使用mmap的C程序都必须重新编译,因为头文件中的标志会包含在二进制文件里。

编辑mmapPOSIX的一部分,但简单浏览后没有发现这些标志在所有平台上是否必须保持相同的值。

6

要在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文件中(直接或间接)包含进来的,这样就没问题了。

撰写回答