Cython 中的枚举成员名称重复 - 重新声明错误?
Posted
技术标签:
【中文标题】Cython 中的枚举成员名称重复 - 重新声明错误?【英文标题】:Duplicate enum member names in Cython - redeclaration error? 【发布时间】: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。有什么解决办法吗?
【问题讨论】:
【参考方案1】:在 C 中,以下代码 would not compile:
enum Foo
A
;
enum Bar
A
;
因为在 C 中,枚举不会引入新的名称范围,因此如果您对 Foo
和 Bar
两种类型使用相同的标识符 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 没有将类型名称(Fruit
、Animal
)包含在生成的枚举值名称中,因此在 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
在生成的代码中,枚举名称将具有模块名称(即Fruit
和Animal
),因此从 C 编译器的角度来看并不相同。
【讨论】:
感谢您的回答。如果 Python 版本在 CPython 上运行良好,我想有一些 hacky 方法来复制它?如果没有更好的方法,我会在 2 周内接受您的答复。以上是关于Cython 中的枚举成员名称重复 - 重新声明错误?的主要内容,如果未能解决你的问题,请参考以下文章
Interface-Class允许静态成员方法到Instance成员方法重新声明,但Class-Class或Interface-Interface不允许[重复]