F2PY:将单元素数组传递给Fortran

时间:2010-01-29 01:40:53

标签: f2py

以下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

为什么这个断言失败了?

2 个答案:

答案 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,它也适用于单元素数组。