从 python 向 Fortran 传递变量会导致错误的值

Passing variables to Fortran from python causes wrong values

基于此,我想使用Python 和Fortran 子例程来操作Fortran 模块的变量。请看下面的例子:

vars.f90

module vars
implicit none
real(kind=selected_real_kind(p=15))      :: fk(10)
end module vars

sub.f90

subroutine sub
    use vars
    print *, "sub: fk(1) = ", fk(1)
    print *, "adding 1 to fk(1)"
    fk(1) = fk(1) + 1
    print *, "fk(1) = ", fk(1)
end

mytest.f90

include "vars.f90"
include "sub.f90"

使用以下命令和 gfortran 完成编译:

f2py -c -m mytest mytest.f90

最后,这是在 Python 3.6.5 控制台中重现问题的测试用例:

>>> import mytest
>>> mytest.vars.fk[1]
0.0
>>> mytest.vars.fk[1]=1.5000
>>> mytest.vars.fk[1]
1.5
>>> mytest.sub()
 sub: fk(1) =   0.12500000000000000     
 adding 1 to fk(1)
 fk(1) =    1.1250000000000000     
>>> mytest.vars.fk[1]
1.890625
>>> 

以我的观点,fk(1)最终应该是2.5。但不幸的是,尽管通过 python 控制台直接访问变量显示了正确的值,但 Fortran 错误地读取了子例程中的变量。修改变量后,python 控制台也显示错误的数字。

对resolve/reason这种行为有什么建议或建议吗?感谢您的帮助!谢谢!

P.S.: 首先我认为这取决于 Python 和 Fortran 处理数组的方式不同(Python 从索引 0 开始,Fortran 从索引 1 开始),但是这不是错误。 mytest.vars.fk[0]调用子程序后不修改(初始值0.0)。

代码有两个问题:

  1. 索引问题,您已经注意到了。您仍然需要在Python中访问fk[0]以获得所需的行为。

  2. 使用selected_real_kind(p=15)进行种类规范。参见 FAQ of F2PY and this related SO answer.

目前,f2py 将您的 varibale 视为默认实数变量(此处为 32 位)而不是双精度。您可以通过创建文件 .f2py_f2cmap(在当前工作目录中)来修复它,其内容为:

{'real':{'selected_real_kind(p=15)': 'double'}}

那将 select "double" 作为参数的相应 C 类型。不幸的是,F2PY 无法检测现代 Fortran 类型。

我将其标记为 f2py: Specifying real precision in fortran when interfacing with python? 的副本,但这里也存在索引问题。看看别人怎么看。