Python 将Numpy数组传递给C函数进行输入和输出
噢,我的天,我是个傻瓜。 调用函数时,我只是省略了第二个和第三个参数。 像个傻瓜。 因为我就是这样。 原始问题如下: 这似乎是一件非常常见的事情,但我找不到相关的教程,而且我对Python 将Numpy数组传递给C函数进行输入和输出,python,numpy,ctypes,ffi,Python,Numpy,Ctypes,Ffi,噢,我的天,我是个傻瓜。 调用函数时,我只是省略了第二个和第三个参数。 像个傻瓜。 因为我就是这样。 原始问题如下: 这似乎是一件非常常见的事情,但我找不到相关的教程,而且我对Numpy和ctypes太无知了,自己也弄不清楚 我在文件ctest.C中有一个C函数 #包括 void cfun(常量void*indatav、int rowcount、int colcount、void*outdatav){ //void cfun(常量double*indata、int rowcount、int co
Numpy
和ctypes
太无知了,自己也弄不清楚
我在文件ctest.C
中有一个C函数
#包括
void cfun(常量void*indatav、int rowcount、int colcount、void*outdatav){
//void cfun(常量double*indata、int rowcount、int colcount、double*outdata){
常数double*indata=(double*)indatav;
double*outdata=(double*)outdatav;
int i;
放置(“我们开始了!”);
对于(i=0;i
(正如您可能猜到的,我最初的参数是double*而不是void*,但我不知道在Python方面该怎么做。我当然很想把它们改回去,但只要它有效,我就不挑剔。)
我用它建立了一个共享的图书馆。
gcc-fPIC-shared-o ctest.so ctest.c
在Python中,我有几个numpy数组,我想把它们传递给C函数,一个作为输入,一个作为输出
indata = numpy.ones((5,6), dtype=numpy.double)
outdata = numpy.zeros((5,6), dtype=numpy.double)
lib = ctypes.cdll.LoadLibrary('./ctest.so')
fun = lib.cfun
# Here comes the fool part.
fun(ctypes.c_void_p(indata.ctypes.data), ctypes.c_void_p(outdata.ctypes.data))
print 'indata: %s' % indata
print 'outdata: %s' % outdata
这不会报告任何错误,但会打印出来
>>> Here we go!
Done!
indata: [[ 1. 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1. 1.]]
outdata: [[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0.]]
outdata数组没有被修改。事实上,如果我再次调用该函数,我会得到一个segfault。这并不奇怪——我真的不知道我在这里做什么。有人能给我指出正确的方向吗?只需将所有四个参数都传递给C函数。将Python代码更改为:
fun(ctypes.c_void_p(indata.ctypes.data), ctypes.c_void_p(outdata.ctypes.data))
致:
虽然不是对原始问题的直接回答,但这里有一种更方便的调用函数的方法。首先,使C函数的原型与普通C中的原型完全相同。因为不需要分别使用
rowcount
和colcount
,我将它们折叠为一个size
参数:
void cfun(const double *indatav, size_t size, double *outdatav)
{
size_t i;
for (i = 0; i < size; ++i)
outdatav[i] = indatav[i] * 2.0;
}
现在,调用函数将非常方便:
indata = numpy.ones((5,6))
outdata = numpy.empty((5,6))
fun(indata, indata.size, outdata)
def wrap_fun(indata, outdata):
assert indata.size == outdata.size
fun(indata, indata.size, outdata)
您还可以定义一个包装器,使其更加方便:
indata = numpy.ones((5,6))
outdata = numpy.empty((5,6))
fun(indata, indata.size, outdata)
def wrap_fun(indata, outdata):
assert indata.size == outdata.size
fun(indata, indata.size, outdata)
我没有在C中调用该函数。我需要吗?抱歉。似乎您正在混合
C
和python
并且我不知道它是如何工作的。事实上将放在C
中调用表明它是从python
代码调用的。但我怀疑您传递给C
函数的内容导致了e问题。如果数组是非连续的,您可能需要numpy.ascontiguousarray()
,例如,.@J.F.Sebastian:您可以向ndpointer()
调用添加flags=“C_contracting”
,以动态检查数组是否是C连续的。(也许我应该将此添加到这个答案中。)<代码>标志< /代码>参数导致<代码> TypeError < /代码>如果输入数组不是连续的.@ j.f.SEBASTAN:这就是我试图暗示的,它会添加动态类型检查。您认为TypeError是正确答案吗?