如何在cython中按值访问枚举类型

时间:2014-04-25 22:38:06

标签: python enums 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

我被告知这应该没有问题,但从我刚才的经历来看并非如此,并且在这篇文章中可以看出:Defining enums in Cython code that will be used in the C part of code

但是,如果我写“return val1”,它本身也不会识别“val1”。这样做的正确方法是什么?

2 个答案:

答案 0 :(得分:7)

您可以在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"已打印。您可以将变量test传递给CC++函数,其方式与cdef函数的显示方式相同。

答案 1 :(得分:1)

在解决了这个问题几个小时之后,我终于找到了合适的解决方案!实际上,这就是我希望Cython为我做的事情。

此解决方案分为两个部分:

  1. 一方面,我们有一个Cython枚举。这个枚举可以通过将C / C ++代码包装在extern块中来产生...

    cdef extern from "header.hpp":
        enum my_c_enum_type:
            val1 = 0;
            val2 = 1;
            val3 = 2;
    

    ...或直接在Cython中

    ctypedef enum my_c_enum_type:
        val1,    #Default value is 0
        val2,    #Default value is 1
        val3     #Default value is 2
    
  2. 另一方面,我们有Python。从Python 3.4开始,有一个支持的类Enum可以模拟该功能(link to official documentation)。在这里,我们应该在纯Python中复制枚举:

    from enum import Enum
    class my_p_enum_type(Enum):
        UNDEFINED=0
        INTEGER=1
        FRACTIONAL=2
        BATCH=3
    

现在,我们有了一个功能相同的精美python类。为了在Python和Cython世界之间进行交互,我们使用:

# from Python to Cython
def func(enum_obj):
    if not isinstance(enum_obj, my_p_enum_type):
         raise TypeError
    # Use in a cython function that accepts only my_c_enum_type Cython enum
    myCythonEnumFunc(enum_obj.value)
    ...

# from Cython to Python
def func():
    # a Cython enum
    cdef my_c_enum_type a_cython_enum = val1
    # creating a python enum
    return my_p_enum_type(a_cython_enum)
    ...

此解决方案将Cython / C枚举(在Python中仅是整数)转换为具有相同特征的适当Python Enum类,并将Python Enum对象内部的值转换为原始Cython类。缺点是您仍然需要维护两个具有相同结构的不同代码段……但是您始终需要使用Cython来做到这一点!