使用F2py实现Python与Fortran变量传递时遇到参数缺失错误的问题
我来帮你分析并解决这个问题~ 先理清楚你遇到的情况:
你写了一个简单的Fortran加法子例程,用f2py编译成testlib2.pyd后,在Python里调用时却被要求传入定义为intent(out)的参数C,这和你看到的示例不太一样,确实有点困惑对吧?
先重现你的场景
你的Fortran代码(testlib2.f):
C SUBROUTINE TESTLIB(A,B,C) C REAL, intent (in) :: A, B REAL, intent (out) :: C C = A + B END SUBROUTINE TESTLIB
编译命令:
python -m numpy.f2py -c -m testlib2 testlib2.f
Python调用代码(testlib.py):
import numpy as np import testlib2 A = 3 B = 2 C = testlib2.testlib(A, B) print("C = ", C)
运行后触发的错误:
File c:\users\bcn\documents\hps\hps fortran\testlib.py:6 C = testlib2.testlib(A, B) TypeError: testlib2.testlib() missing required argument 'c' (pos 3).
问题原因
本质上是因为Fortran的SUBROUTINE(子例程)本身没有返回值,所有参数都是按引用传递的——哪怕你声明了intent(out),f2py默认还是会保留Fortran的原生调用逻辑,要求你传入这个参数,让子例程去修改它的值,而不是自动把它作为Python函数的返回值。
你看到的示例里之所以不用传入out参数,是因为那些示例要么修改了f2py的包装逻辑,要么用了Fortran的FUNCTION(函数)而非SUBROUTINE。
两种解决方法
方法1:修改Python调用逻辑,适配Fortran子例程的原生调用方式
既然f2py默认要求传入c参数,那我们可以初始化一个变量传入它,Fortran子例程会直接修改这个变量的值:
import numpy as np import testlib2 A = 3.0 # 建议用浮点数,和Fortran的REAL类型严格匹配 B = 2.0 C = 0.0 # 初始化一个浮点数变量 testlib2.testlib(A, B, C) # 调用子例程,直接修改C的值 print("C = ", C) # 此时C已经被更新为5.0
方法2:重新编译,让f2py把out参数包装成Python风格的返回值
如果你想保持Python代码里的函数式调用(C = testlib2.testlib(A,B)),可以给Fortran代码加上f2py的专用注释指令,告诉它把C作为返回值处理:
修改后的Fortran代码:
C SUBROUTINE TESTLIB(A,B,C) C REAL, intent (in) :: A, B REAL, intent (out) :: C Cf2py intent(out) C # 明确告诉f2py这是输出参数 Cf2py returns C # 让f2py把C作为函数的返回值 C = A + B END SUBROUTINE TESTLIB
然后重新用原来的编译命令生成testlib2.pyd:
python -m numpy.f2py -c -m testlib2 testlib2.f
之后你的原Python代码就可以正常运行了,不需要修改调用方式~
另外补充一下:你提到为了Python3.12的f2py安装了meson、ninja等工具,这是正常的——Python3.12起f2py切换到了meson作为构建系统,这些是必要的依赖。
备注:内容来源于stack exchange,提问作者Rathpr

