首页 > 解决方案 > Cython 中的枚举成员名称重复 - 重新声明错误?

问题描述

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。有什么解决方法吗?

标签: pythonenumscythoncythonize

解决方案


在 C 中,以下代码无法编译

enum Foo{
    A
};

enum Bar{
    A
};

因为在 C 中,枚举不会引入新的名称范围,因此如果您A对两种类型FooBar.

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 没有将类型名称 ( Fruit, Animal) 包含到生成的枚举值名称中,因此在 Cython 中您可以将它们区分为Fruit.UNKNOWNAnimal.UNKNOWN,它们将映射到相同的 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 编译器的角度来看是不一样的。


推荐阅读