F2PY:将单元素数组传递给 Fortran
以下 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
为什么此断言失败?
The following Fortran code fills a 2D array x with value v
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
When calling this function from Python:
x = numpy.array([[[0.0]]],order='F')
fill(x[:,:,0],2.0)
assert(x[0,0,0]==2.0) # Assertion failed
Why is this assertion failing ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您希望 x 将值传递回调用者,则应将 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
x should be declared as
intent(inout)
if you want it to pass values back to the caller.However this causes an additional problem because passing array slices doesn't work for
intent(inout)
arrays. In this simple example you can get around it by calling from python:fill(x, 2.0)
.If you really wanted to pass a slice then you need to declare x as intent(in,out), and call from python:
x[:,:,0] = fill(x[:,:,0],2.0)
The description of the different attributes can be found at:
http://cens.ioc.ee/projects/f2py2e/usersguide/index.html#attributes
我刚刚遇到这个问题。
intent(inout)
和intent(inplace)
都没有修复它。问题显然出在fortranobject.c
中的数组检查例程array_from_pyobj()
中,该例程随f2py
一起提供,并与构建的每个模块链接。 array_from_pyobj() 尽一切努力将任何输入转换为形状正确的连续数组,并进行许多检查。其中之一无法正确处理单元素数组,因此会生成副本而不是处理原始数组。人们可以解决这个问题,但是……好吧……无论如何,我不想在性能库的接口中出现任何这种多态性的东西……我有一个Python类包装了库调用,它已经保证了所有参数被正确地传递。
所以我的解决办法是制作我自己的
fortranobject.c
副本,并简单地将array_from_pyobj()
替换为以下虚拟版本:我的计划是使用原始的
fortranobject .c
在我的 Python 包装类的开发过程中,无可否认,每次调用库函数时出错时,获得温和的错误消息而不是严重崩溃是一个优势。一旦我确定所有库调用都有效,我将使用自定义的fortranobject.c
,它也适用于单元素数组。I just had this issue. Neither
intent(inout)
norintent(inplace)
fixed it. The problem is obviously in the array checking routinearray_from_pyobj()
infortranobject.c
, which ships withf2py
and is linked with every module one builds.array_from_pyobj()
makes every effort that any input is converted to a properly shaped contiguous array, doing many many checks. One of them does not work properly with single-element arrays, such that a copy is made instead of working on the original array.One could fix that, but ...well... I don't want any of this polymorphism stuff in an interface to a performance library anyway... I have a Python class wrapping the library calls that already guarantees that all the arguments are passed on correctly.
So my fix was to make my own copy of
fortranobject.c
and simply replacearray_from_pyobj()
by the following dummy version:My plan is to use the original
fortranobject.c
during development of my Python wrapper class, where admittedly it is an advantage to get gentle error messages instead of hard crashes every time one makes a mistake calling a library function. Once I'm sure that all the library calls work, I'll use my customfortranobject.c
, which also works with single-element arrays.