如何通过值访问Cython中的枚举类型
我拿到了一段代码,内容大致如下:
在 "header.hpp" 文件中:
enum class my_enum_type {
val1 = 0;
...
}
在 "header_lib.pyx" 文件中:
cdef extern from "header.hpp":
enum my_enum_type:
val1 = 0;
...
...
在 "header_lib.pyx" 文件的后面部分:
def foo():
...
return my_enum_type.val1
有人告诉我这段代码应该没有问题,但根据我刚才的经验,情况并不是这样。这个问题在这个帖子中也有体现:在 Cython 代码中定义枚举,以便在 C 代码部分使用。
不过,如果我写 "return val1",它也不单独识别 "val1"。那正确的做法是什么呢?
3 个回答
你可以使用cpdef直接在cython中创建一个Python的枚举类型:
cpdef enum my_enum_type:
val1 = 0
...
这个内容在文档中提到得很少(可以搜索cpdef enum
)
为了让Cython/C/C++的枚举类和Python的枚举类功能保持一致,我提出了一个用镜像类的解决方案。这个方案分为两个部分:
一方面,我们有一个Cython/C/C++的枚举。这种枚举可以通过在extern块中包装C/C++代码来创建...
cdef extern from "header.h": enum my_c_enum_type: OPT1 = 0, OPT2, OPT3,
...或者直接在Cython中定义。
ctypedef enum my_cy_enum_type: OPT1=0, #Default value is 0 OPT2, #Default value is 1 OPT3, #Default value is 2
另一方面,我们有Python。从Python 3.4开始,支持一个叫做Enum的类,它模拟了这种功能(官方文档链接)。在这里,我们应该在纯Python中复制枚举元素。你可以使用
auto
函数来填充枚举,就像在C/C++/Cython中那样:from enum import Enum, auto class my_py_enum_type(Enum): OPT1=0 OPT2=auto() OPT3=auto()
现在,为了使用这个双重的Python和Cython解决方案:
# PYTHON: we use the my_py_enum_type Enum
enum_obj = my_py_enum_type(1) # Corresponds to OPT2
print(enum_obj.value, enum_obj.name) # We can access the value and the name
#> 1, OPT2
s='OPT2'; enum_obj = getattr(my_py_enum_type, s) # We can create them from the string 'OPT2'
# PYTHON TO CYTHON
def func(enum_obj):
if not isinstance(enum_obj, my_py_enum_type):
raise TypeError
# Use in a cython function that accepts only my_c_enum_type Cython enum
myCythonEnumFunc(enum_obj.value) # Convert to C/Cython enum using value
...
# CYTHON TO PYTHON
def func():
# a Cython enum
cdef my_c_enum_type cy_enum_obj = val1
# creating a python enum
return my_p_enum_type(cy_enum_obj) # Convert using the full cy_enum
...
这个方案将Cython/C的枚举(在Python中只是简单的整数)转换成一个具有相同特性的Python Enum类,并将Python Enum对象中的值转换回原来的Cython类。这样你就能同时享受到两者的优点!
你可以在Cython中这样声明一个enum
:
ctypedef enum options: OPT1, OPT2, OPT3
或者这样:
ctypedef enum options:
OPT1,
OPT2,
OPT3
一个例子可以是:
def main():
cdef options test
test = OPT2
f(test)
cdef void f(options inp):
if inp == OPT1:
print('OPT1')
elif inp == OPT2:
print('OPT2')
elif inp == OPT3:
print('OPT3')
当你运行main()
时,你会看到打印出"OPT2"
。你可以像这里展示的cdef
函数那样,把变量test
传递给一个C
或C++
的函数。