Cython中无法将C数组作为memoryview传递的问题咨询
问题:Cython中C数组无法传递给接受memoryview的函数
代码示例
.pyx文件(yy.pyx)
# yy.pyx def foo(double[::1] args): cdef double[3] v = [args[0], args[1], 0] bar(v) def bar(double[::1] args): pass
主程序(main.py)
import numpy as np import pyximport pyximport.install() import yy yy.foo(np.arange(2.0))
运行错误信息
In [3]: run main.py --------------------------------------------------------------------------- TypeError Traceback (most recent call last) File ~/src/cython-numpy/main.py:8 4 pyximport.install() 6 import yy ----> 8 yy.foo(np.arange(2.0)) File ~/src/cython-numpy/yy.pyx:3, in yy.foo() 1 def foo(double[::1] args): 2 cdef double[3] v = [args[0], args[1], 0] ----> 3 bar(v) 4 5 def bar(double[::1] args): File ~/src/cython-numpy/yy.pyx:5, in yy.bar() 3 bar(v) 4 ----> 5 def bar(double[::1] args): 6 pass 7 File stringsource:660, in View.MemoryView.memoryview_cwrapper() File stringsource:350, in View.MemoryView.memoryview.__cinit__() TypeError: a bytes-like object is required, not 'list'
原因分析
Cython中cdef double[3] v定义的是C静态数组,它只是一块连续的内存区域,但Cython不会自动将其转换为Python层面的memoryview对象。而bar函数的参数double[::1] args要求接收的是memoryview(内存视图),这种类型仅支持能暴露内存缓冲区的Python对象(比如numpy数组、array.array),C静态数组不属于这类对象,因此传递时会触发类型错误。
使用array.array无报错是因为它是Python标准库对象,本身支持导出内存缓冲区,可以被memoryview正确解析。
解决方法
方法1:手动生成memoryview
修改foo函数中调用bar的代码,通过切片操作生成指向C数组的memoryview:
def foo(double[::1] args): cdef double[3] v = [args[0], args[1], 0] bar(v[:]) # 通过切片创建memoryview def bar(double[::1] args): pass
方法2:修改bar的参数类型为C数组
如果不需要bar接收其他类型的内存视图,可以直接将其参数改为固定长度的C数组:
def foo(double[::1] args): cdef double[3] v = [args[0], args[1], 0] bar(v) def bar(double[3] args): # 参数改为C数组类型 pass
这种方式限制了参数只能是固定长度的C数组,灵活性不如memoryview。
内容的提问来源于stack exchange,提问作者nos
相关产品推荐
相关产品推荐

