3

以下 Fortran 代码用值 v 填充二维数组 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

为什么这个断言失败了?

4

2 回答 2

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

于 2010-10-21T03:39:11.587 回答
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的,诚然,每次调用库函数出错时,获得温和的错误消息而不是硬崩溃是一个优势。一旦我确定所有库调用都有效,我将使用我的 custom fortranobject.c,它也适用于单元素数组。

于 2013-10-28T19:30:24.067 回答