如何在Cython模块中将#defined的C值暴露给Python?
我想把这里定义的整数常量(比如 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
>>>