我试图让一个测试项目工作,用Python调用带有数组参数的C函数:
TEST.CPP :
void testFn(int arr[]);
void testFn(int arr[])
{
arr[0] = 1;
arr[1] = 2;
}
caller.pyx :
import ctypes
cdef extern from "test.cpp":
void testFn(int arr[])
def myTest():
a = [0, 0]
arr = a.ctypes.data_as(ctypes.POINTER(ctypes.c_integer))
testFn(arr)
print(arr)
setup.caller.py :
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
sourcefiles = ['caller.pyx']
ext_modules = [Extension("caller", sourcefiles)]
setup(
name = 'test app',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules
)
但是当我尝试构建项目时,我收到一个错误:
$ python setup.caller.py build_ext --inplace
running build_ext
cythoning caller.pyx to caller.c
Error compiling Cython file:
------------------------------------------------------------
...
def myTest():
a = [0, 0]
arr = a.ctypes.data_as(ctypes.POINTER(ctypes.c_integer))
testFn(arr)
^
------------------------------------------------------------
caller.pyx:13:11: Cannot convert Python object to 'int *'
答案 0 :(得分:4)
这个问题经常出现,但是我无法找到一个好的重复目标,这将超越"只需这样做就可以了。#/ p>
这是一种非常常见的情况:您尝试将一些python数据结构传递给需要指针int *, double *,...
的c代码。但是指针不是python对象,所以我们不能将它们从/传递给python代码。
有两种最常见的情况:
array.array
,numpy-arrays)。list
)<强> 1。通过记忆视图传递:
在python中我们无法以某种方式获取指针,因此必须在cython中完成。我将array.array
或numpy.array
传递给cython函数的第一选择是内存视图(因为array.array
是一个内存视图,没有开销):
def myTest(int[:] arr):
testFn(&arr[0])
现在从python中调用它:
>>> import array
>>> a=array.array('i', [0]*2)
>>> import caller
>>> caller.myTest(a)
>>> a
array('i', [1, 2]) #it worked
以下是重要的
int[:]
是一个python对象(一个类型化的内存视图),因此可以传递给python函数(def
或cpdef
)。&arr[0]
用于获取内存视图缓冲区的地址。其结果是int *
类型。array.array('I', [0]*2)
传递给它,因为它不是int
- 内存视图而是{{ {1}} - 存储器视<强> 2。传递非连续记忆(例如列表):
unsigned int
和Co有更多的工作:信息不存储在普通的c-arrays中,所以我们需要先将它们复制到连续的内存中,将这个temp变量传递给我们的c-code并复制结果回到列表,我们的cython函数可能如下所示
list
现在重新加载import array
def myTest2(lst):
tmp=array.array('i', lst)
myTest(tmp)
lst.clear()
lst.extend(tmp)
模块后:
caller
因此,可以将列表的内容传递给c函数,但如果您需要使用c代码进行数据交换,基本上您希望使用>>> lst=[0,0]
>>> caller.myTest2(lst)
[1, 2]
或array.array
。