如何通过值访问Cython中的枚举类型

6 投票
3 回答
12057 浏览
提问于 2025-04-18 04:18

我拿到了一段代码,内容大致如下:

在 "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 个回答

2

你可以使用cpdef直接在cython中创建一个Python的枚举类型:

cpdef enum my_enum_type:
    val1 = 0
    ...

这个内容在文档中提到得很少(可以搜索cpdef enum

5

为了让Cython/C/C++的枚举类和Python的枚举类功能保持一致,我提出了一个用镜像类的解决方案。这个方案分为两个部分:

  1. 一方面,我们有一个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
    
  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类。这样你就能同时享受到两者的优点!

10

你可以在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传递给一个CC++的函数。

撰写回答