【问题标题】:Duplicate enum member names in Cython - redeclaration error?Cython 中的枚举成员名称重复 - 重新声明错误?
【发布时间】:2018-11-12 05:04:18
【问题描述】:

Cython 似乎不允许我重用枚举成员名称。

我正在尝试对以下枚举进行 cythonize:

from enum import Enum

class Fruit(Enum):

    UNKNOWN = 0
    APPLE = 1
    ORANGE = 2

class Animal(Enum):

    UNKNOWN = 0
    DOG = 1
    CAT = 2

但以下导致'UNKNOWN' redeclared编译错误:

cpdef enum Fruit:

    UNKNOWN = 0
    APPLE = 1
    ORANGE = 2    

cpdef enum Animal:

    UNKNOWN = 0
    DOG = 1
    CAT = 

我应该如何解决上述问题?

另外,我最好使用NULL 作为枚举成员名称,而不是UNKNOWN。但似乎NULL 是 Cython 的特权关键字,尽管它不适用于 CPython。有什么解决办法吗?

【问题讨论】:

    标签: python enums cython cythonize


    【解决方案1】:

    在 C 中,以下代码 would not compile:

    enum Foo{
        A
    };
    
    enum Bar{
        A
    };
    

    因为在 C 中,枚举不会引入新的名称范围,因此如果您对 FooBar 两种类型使用相同的标识符 A,则会发生名称冲突。

    Cython 会翻译(如果它只是应用其通常的方案并且不会因编译器错误而停止):

    #foo.pyx
    cpdef enum Fruit:
        UNKNOWN = 0   
    
    cpdef enum Animal:
        UNKNOWN = 0
    

    类似

    enum __pyx_t_3foo_Fruit {
      __pyx_e_3foo_UNKNOWN = 0
    };
    
    enum __pyx_t_3foo_Animal {
      __pyx_e_3foo_UNKNOWN = 0
    };
    

    正如我们所见,这不是有效的 C,因此 Cython 的选择是生成错误。一个“问题”是 Cython 没有将类型名称(FruitAnimal)包含在生成的枚举值名称中,因此在 Cython 中,您可以将它们区分为 Fruit.UNKNOWN 和 @ 987654331@,它们将映射到相同的 C 标识符。

    至少有两种选择:

    A: C 中通常的策略是使用前缀来区分枚举,例如:

    cpdef enum Fruit:
           FRUIT_UNKNOWN = 0
    
    cpdef enum Animal:
          ANIMAL_UNKNOWN = 1
    

    或 B:您可以让 Cython 完成这项工作,方法是将它们放在不同的 pxd 文件中,这些文件会导入到生成的 pyx 文件中:

    # Fruit.pxd
    cpdef enum Fruit:
        UNKNOWN = 0
    
    #Animal.pxd
    cpdef enum Animal:
        UNKNOWN = 0
    
    # foo.pyx:
    cimport Fruit
    cimport Animal
    
    # use Fruit.UNKNOWN and Animal.UNKNOWN
    

    在生成的代码中,枚举名称将具有模块名称(即FruitAnimal),因此从 C 编译器的角度来看并不相同。

    【讨论】:

    • 感谢您的回答。如果 Python 版本在 CPython 上运行良好,我想有一些 hacky 方法来复制它?如果没有更好的方法,我会在 2 周内接受您的答复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-14
    • 1970-01-01
    • 2019-03-04
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多