f2py转换C/Fortran数组失败,求解决方法(附代码)
解决Fortran-Python Wrapper中的数组转换错误
问题场景
编写Fortran到Python的wrapper时,调用出现如下错误:
ValueError: failed to create intent(cache|hide)|optional array -- must have defined dimensions, but dims[0] = -1 The above exception was the direct cause of the following exception: Traceback (most recent call last): File "wrap.py", line 12, in <module> test.wrap(A, B) ValueError: failed in converting hidden `c' of test.wrap to C/Fortran array
涉及代码如下:
Python代码(原wrap.py)
import numpy as np A = np.random.random((5,5)) B = np.random.random((5,5)) C = np.zeros((5, 5)) A = np.asfortranarray(A) B = np.asfortranarray(B) C = np.asfortranarray(C) test.wrap(A, B) # 错误:未传入输出参数C print(C[0,0])
Fortran代码(test.f90)
subroutine wrap(A, B, C) implicit none real, intent(in) :: A(:, :), B(:, :) real, intent(out) :: C(:, :) integer :: m, n, p m = size(A, 1) n = size(A, 2) p = size(B, 2) if (n /= size(B, 1)) then print *, "Error: Incompatible dimensions for matrix multiplication" return end if C = matmul(A, B) end
编译命令:
python -m numpy.f2py -c --f90flags='-O3' -m test test.f90
错误原因
Fortran子程序wrap中,C是**intent(out)**的输出参数,但Python调用时未传入该参数。f2py无法自动推断输出数组C的维度(维度依赖于输入A和B的大小),因此无法创建符合要求的数组,导致转换失败。
修复方案
方案一:Python调用时传入预分配的C数组
这是最直接的解决方法:既然已经在Python中创建了C数组,只需在调用时将其传入wrap函数,让f2py直接使用已有的数组空间存储计算结果。
修改后的Python代码:
import numpy as np A = np.random.random((5,5)) B = np.random.random((5,5)) C = np.zeros((5, 5)) A = np.asfortranarray(A) B = np.asfortranarray(B) C = np.asfortranarray(C) test.wrap(A, B, C) # 传入输出参数C print(C[0,0])
方案二:通过f2py接口注释指定输出数组维度
如果希望Python调用时不需要手动传入C(让f2py自动创建),可以在Fortran代码中添加f2py专用注释,明确C的维度与输入参数的关系:
修改后的Fortran代码:
subroutine wrap(A, B, C) implicit none real, intent(in) :: A(:, :) real, intent(in) :: B(:, :) real, intent(out) :: C(:, :) integer :: m, n, p !f2py intent(hide) :: m, n, p !f2py dimension(C) = (size(A,1), size(B,2)) m = size(A, 1) n = size(A, 2) p = size(B, 2) if (n /= size(B, 1)) then print *, "Error: Incompatible dimensions for matrix multiplication" return end if C = matmul(A, B) end
重新编译后,Python调用时可省略C参数,函数会直接返回计算后的C数组:
import numpy as np A = np.random.random((5,5)) B = np.random.random((5,5)) A = np.asfortranarray(A) B = np.asfortranarray(B) C = test.wrap(A, B) # 直接获取返回的C数组 print(C[0,0])
内容的提问来源于stack exchange,提问作者Chungji
相关产品推荐
相关产品推荐

