这个问题经常出现,但是我找不到一个很好的重复目标,这超出了“只要这样做就行”的范围。
这是一种非常常见的情况:您尝试将一些python数据结构传递给需要指针的c代码
int *, double*,...。但是,指针不是python对象,因此我们无法将它们从python代码传递到python代码。
用Cython可以自动处理转换到
int,
double,
float等等,甚至
char *(它是一个空终止的c-字符串)和一些STL-
容器,而不是指针(
char *作为一个例外)。
有两种最常见的情况:
- python数据的内部表示形式已经是一个c数组(
array.array
,numpy-arrays)。 - 内部表示形式不是连续数组(例如
list
)
1.通过内存视图传递:
在python中,我们无法以某种方式获取指针,因此必须在cython中完成。将
array.arrayor或
numpy.array(或任何其他支持buffer-
protocol的python对象
ctypes.Array,例如,参见此SO-
question)传递给cython函数的首选是内存视图:
def myTest(int[:] arr): testFn(&arr[0])
现在从python调用它:
>>> import array>>> a=array.array('i', [0]*2)>>> import caller>>> caller.myTest(a)>>> aarray('i', [1, 2]) #it worked以下重要
int[:]
是python对象(类型化的内存视图),因此可以将其传递给python函数(def
或cpdef
)。&arr[0]
用于获取内存视图的缓冲区的地址。其结果是类型int *
。- 该函数的调用是“类型安全的”,您不能例如
array.array('I', [0]*2)将其传递给它,因为它不是int
-memory-view,而是unsigned int
-memory-view。
2.传递非连续内存(例如列表):
list与Co.合作的还有更多工作:信息没有存储在普通的c数组中,因此我们需要先将其复制到连续内存中,将此temp变量传递给我们的c代码,然后将结果复制回列表中,即cython函数可能如下所示
import arraydef myTest2(lst): tmp=array.array('i', lst) myTest(tmp) lst.clear() lst.extend(tmp)现在,在重新加载
caller模块后:
>>> lst=[0,0]>>> caller.myTest2(lst)[1, 2]
因此,可以将列表的内容传递给c函数,但是基本上您想使用它,
array.array或者
numpy.array如果需要使用c代码进行数据交换。



