Cython 编译错误“常量表达式中不允许”
Posted
技术标签:
【中文标题】Cython 编译错误“常量表达式中不允许”【英文标题】:Cython compilation error "Not allowed in a constant expression" 【发布时间】:2018-02-28 14:39:27 【问题描述】:以下
cimport cython
@cython.boundscheck(False)
def boundtest():
cdef int r=4
cdef double l[3]
工作正常。但是当我尝试这个时:
cimport cython
@cython.boundscheck(False)
def boundtest():
cdef int r=4
cdef double l[r]
我收到以下错误:
[1/1] Cythonizing test.pyx
Error compiling Cython file:
------------------------------------------------------------
...
cimport cython
@cython.boundscheck(False)
def boundtest():
cdef int r=4
cdef double l[r]
^
------------------------------------------------------------
test.pyx:13:20: Not allowed in a constant expression
添加装饰器是因为找到了 this 相关的 stackexchange 帖子并阅读了 Kurt W. Smith 的 Cython 书。据我所知,这应该可以告诉 Cython 不要担心可能由动态索引变量导致的越界错误,但由于某种原因它没有。我也尝试在编译器选项和全局范围内更改边界检查无济于事。
如果不是 Cython 文档声称是最新的,我会认为 boundscheck 已经贬值了。
【问题讨论】:
【参考方案1】:失败与cython.boundscheck
无关。
Boundchecking 只是检查您是否尝试访问不存在的数组元素。例如,如果您有一个大小为 4 的数组并尝试访问元素 5 - 使用 boundscheck(True)
它将给您一个异常,使用 boundscheck(False)
它将导致未定义的行为(可能导致分段错误)。
编译失败的原因还有一个:不能创建动态长度的静态数组!在编译时需要知道元素的数量,这只是c 强制执行的(我猜)。
但是您可以将r
定义为compile time:
DEF r=4
cimport cython
@cython.boundscheck(False)
def boundtest():
cdef double l[r]
但是,您可以简单地创建一个 NumPy 数组并将其存储在 memoryview 变量中:
cimport cython
import numpy as np
@cython.boundscheck(False)
def boundtest():
cdef int r=4
cdef double[:] l = np.empty(r, dtype=np.double)
【讨论】:
成功了,非常感谢!我希望链接帖子中的 OP 能够更明确地更改他的代码以使用 memoryview 变量。 @Takoda Cython 结合了 Python 和 C,因此需要对两者都有一些了解才能正确使用。可能只是“假设”您不使用cdef double l[r]
创建动态长度数组,而仅使用 cdef double l[4]
等已知常量。
奇怪的是 Cython 不支持 C99 VLA,但对它们有好处。 VLA 很危险。以上是关于Cython 编译错误“常量表达式中不允许”的主要内容,如果未能解决你的问题,请参考以下文章
python / cython编译pyx:致命错误:capsule.h:没有这样的文件或目录