以下Fortran代码使用值v
填充2D数组x subroutine fill(x,v,m,n)
real*8 x(m,n),v
integer m,n,i
cf2py intent(in) :: x,v,m,n
forall(i=1:m,j=1:n) x(i,j) = v
end
从Python调用此函数时:
x = numpy.array([[[0.0]]],order='F')
fill(x[:,:,0],2.0)
assert(x[0,0,0]==2.0) # Assertion failed
为什么这个断言失败了?
答案 0 :(得分:3)
x声明为intent(inout)
。
然而,这会导致另一个问题,因为传递数组切片对intent(inout)
数组不起作用。在这个简单的例子中,您可以通过调用python来解决它:
fill(x, 2.0)
。
如果你真的想传递一个切片,那么你需要将x声明为intent(in,out),并从python调用:
x[:,:,0] = fill(x[:,:,0],2.0)
可以在以下位置找到不同属性的说明:
http://cens.ioc.ee/projects/f2py2e/usersguide/index.html#attributes
答案 1 :(得分:0)
我刚遇到这个问题。 intent(inout)
和intent(inplace)
都没有修复它。问题显然出现在array_from_pyobj()
中的数组检查例程fortranobject.c
中,该例程随f2py
一起提供,并与构建的每个模块链接。 array_from_pyobj()
尽一切努力将任何输入转换为形状正确的连续数组,进行许多检查。其中一个与单元素数组无法正常工作,因此无需复制原始数组。
有人可以解决这个问题,但是......好吧......我不希望在性能库的接口中有任何这种多态性的东西...我有一个Python类包装库调用已经保证了所有参数都正确传递。
所以我的修复是制作我自己的fortranobject.c
副本,只需用以下虚拟版本替换array_from_pyobj()
:
extern PyArrayObject *
array_from_pyobj(const int type_num, npy_intp *dims,
const int rank, const int intent, PyObject *obj) {
int i;
PyArrayObject *arr = (PyArrayObject *)obj;
for (i=0; i<arr->nd; ++i)
dims[i] = arr->dimensions[i];
return arr;
}
我的计划是在我的Python包装器类的开发过程中使用原始fortranobject.c
,不可否认,每次调用库函数时出错都会获得温和的错误消息而不是硬崩溃。一旦我确定所有库调用都有效,我将使用我的自定义fortranobject.c
,它也适用于单元素数组。