如何在Cython模块中将#defined的C值暴露给Python?

35 投票
3 回答
11057 浏览
提问于 2025-04-16 15:56

我想把这里定义的整数常量(比如 ACTIVE_TAG 等)

//island management, m_activationState1
#define ACTIVE_TAG 1
#define ISLAND_SLEEPING 2
#define WANTS_DEACTIVATION 3
#define DISABLE_DEACTIVATION 4
#define DISABLE_SIMULATION 5

作为我正在开发的 Cython 模块的普通属性,这样 Python 应用程序代码就可以访问它们(以便将它们传递给以这些常量为基础的封装 API)。

我尝试过用 cdef 定义这些常量为整数或枚举,但这两种方法都没有把值绑定到 Cython 模块的属性上。还有什么其他的选择吗?

3 个回答

0

示例头部:

// myheader.hh
#ifndef MYHEADER
#define MYHEADER

#define NONE 0

#endif

根据我的经验,针对类似的情况,如果没有使用 const 关键字,就会创建一个变量,而这个变量并不是像 #define 那样的常量。我发现Cython生成的C++文件末尾有一些赋值给 NONE 的情况,而对宏进行赋值是被禁止的。

cdef extern from "myheader.hh":
    int NONE

这才是真正的常量:

cdef extern from "myheader.hh":
    const int NONE

Cython中没有 const 关键字的bug:https://github.com/cython/cython/issues/2621

6

在我的情况下,这个方法有效。也许对其他人也有帮助:

我需要从一个Linux内核库中导出一个#define。这个方法对我来说很有效:

# your_pxd_file.pxd
cdef extern from "sched.h": #here are lots of `#define`'s clauses. something like the link: https://github.com/spotify/linux/blob/master/include/linux/sched.h
    cdef enum:
        CLONE_NEWNS

在你的.pyx文件中:

from your_compiled_cython_package cimport CLONE_NEWNS

print(CLONE_NEWNS)

希望这对其他人也能像对我一样有帮助 =)

35

这里有一种方法,虽然看起来有点繁琐,但实际上可以为任何给定的 .h 文件自动化处理:

第一步:把你想要的所有常量放到一个文件里,比如叫 bulletdefs.h,这个文件里包含了 #defines,但是前面加了下划线,例如:

#define _ACTIVE_TAG 1
#define _ISLAND_SLEEPING 2
#define _WANTS_DEACTIVATION 3
#define _DISABLE_DEACTIVATION 4
#define _DISABLE_SIMULATION 5

第二步:在你的模块的 pyx 文件里插入一个部分,比如叫 bullet.pyx

cdef extern from "bulletdefs.h":
    cdef int _ACTIVE_TAG
    cdef int _ISLAND_SLEEPING
    cdef int _WANTS_DEACTIVATION
    cdef int _DISABLE_DEACTIVATION
    cdef int _DISABLE_SIMULATION

ACTIVE_TAG = _ACTIVE_TAG
ISLAND_SLEEPING = _ISLAND_SLEEPING
WANTS_DEACTIVATION = _WANTS_DEACTIVATION
DISABLE_DEACTIVATION = _DISABLE_DEACTIVATION
DISABLE_SIMULATION = _DISABLE_SIMULATION

然后,当你编译你的模块时,你应该能看到预期的效果:

Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import bullet
>>> bullet.ACTIVE_TAG
1
>>> bullet.DISABLE_SIMULATION
5
>>>

撰写回答