为什么用f2py编制了Fortran函数返回零,当我改变结果变量的名称?

问题描述 投票:2回答:1

当我调用下面的函数,它返回1预期:

integer function my_func() result(myresult)
    myresult = 1
end function my_func

但是,当我修改返回值的名称以字母“R”,则该函数返回0

integer function my_func() result(rresult)
    rresult = 1
end function my_func

是什么原因造成的?我首先想到的是,它涉及到隐式类型,但功能是指定implicit none一个模块内。

下面是完整的模块

module my_mod
implicit none

contains

integer function my_func() result(myresult)
    myresult = 1
end function my_func

end module my_mod

我使用Fortran 90的与gfortran编译。

编辑

这是一个完整的程序来说明问题

Makefile文件:

.PHONY: pytest clean

CYTHON_LIB = fortran_mods.cpython-37m-x86_64-linux-gnu.so
FFLAGS += -fdefault-real-8

pytest: $(CYTHON_LIB)
        ./tests.py

$(CYTHON_LIB): my_mod.F90
        f2py -c -m fortran_mods my_mod.F90 --f90flags="$(FFLAGS)"

clean:
        rm *.so

my_mod.F90:

module my_mod
implicit none

contains

!********************************************************

integer function my_func_without_r() result(myresult)
    myresult = 1
end function

integer function my_func_with_r() result(rresult)
    rresult = 1
end function

end module my_mod

tests.朋友

#!/usr/bin/env python3
import fortran_mods
from fortran_mods import *

print("with r:", my_mod.my_func_with_r())
print("without r:", my_mod.my_func_without_r())

make pytest运行和FFLAGS += -fdefault-real-8包含在Makefile中的输出是

with r: 0.0
without r: 1

否则是

with r: 1.0
without r: 1
fortran f2py
1个回答
4
投票

这里的问题是绝对有F2PY如何包装的Fortran语言功能,而不是Fortran代码本身。

为了获得更多的洞察F2PY如何包装的功能(尤其是如果事情不工作了如预期),它总是有助于过程分成几部分(见The smart way)。因此,首先创建一个签名文件,让你看到F2PY如何解释你的代码。为了您的具体的例子,运行:

f2py -m fortran_mods -h my_mod.pyf my_mod.F90

这将产生一个签名文件my_mod.pyf看起来像这样:

python module fortran_mods ! in 
    interface  ! in :fortran_mods
        module my_mod ! in :fortran_mods:my_mod.F90
            function my_func_without_r() result (myresult) ! in :fortran_mods:my_mod.F90:my_mod
                integer :: myresult
            end function my_func_without_r
            function my_func_with_r() result (rresult) ! in :fortran_mods:my_mod.F90:my_mod
                real :: rresult
            end function my_func_with_r
        end module my_mod
    end interface 
end python module fortran_mods

显然F2PY误认my_func_with_r的结果变量rresultreal。你可以简单地替换在real :: rresult预期integer :: rresultmy_mod.pyf,采取F2PY包装的下一/第二个步骤,并使用校正签名文件编译:

f2py -c my_mod.pyf my_mod.F90

你的Python脚本现在应该得到所需要的输出。

如果你有很多的功能包修改签名文件的这种做法可能不期望。什么可能会造成难度F2PY是你的函数定义使用结果变量,没有类型定义为它们在函数体中出现(即一个F2PY问题,而不是一个Fortran问题)。如果你改变你的函数定义到例如为:

function my_func_with_r() result(rresult)
    integer :: rresult
    rresult = 1
end function

要么

integer function my_func_with_r()
    my_func_with_r = 1
end function

你可以做F2PY包装一步到位,你做了最初的,应该仍然得到正确的输出。

最后,我将添加其他投票在评论中提出的问题:环绕功能时F2PY是自找麻烦使用-fdefault-real-8。为了make a Fortran procedure callable from Python,F2PY创建:

一个Python C / API扩展模块(称为包装器模块),它实现一个Python扩展函数(用C,称为包装函数),后者又调用给定的Fortran程序。

这整个过程是基于F2PY如何从你的Fortran源代码解释数据类型 - 如果源代码与改变声明的数据类型的编译器标志编译,事情都会最终破裂(直接类似于real / integer不匹配您的原问题是有关)。为您的变量和函数的数据类型,因此应该在Fortran代码本身进行明确设置,看到特别是有关F2PY一般的Fortran的here参数,here kindhere

© www.soinside.com 2019 - 2024. All rights reserved.