Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当我更改结果变量的名称时,为什么用f2py编译的Fortran函数返回零?_Fortran_F2py - Fatal编程技术网

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

当我更改结果变量的名称时,为什么用f2py编译的Fortran函数返回零?,fortran,f2py,Fortran,F2py,调用以下函数时,它会按预期返回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 这是什么原因造成的?我的第一个想法是它与隐式类型相关,但函数位于一个指定隐式无的

调用以下函数时,它会按预期返回
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
这是什么原因造成的?我的第一个想法是它与隐式类型相关,但函数位于一个指定
隐式无
的模块中

这是完整的模块

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进行编译

编辑

下面是一个完整的程序来演示这个问题

生成文件:

.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.py

#!/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

这里的问题肯定是F2PY如何包装Fortran函数,而不是Fortran代码本身

为了更深入地了解F2PY是如何包装函数的(特别是在事情没有按预期进行的情况下),将流程分成多个部分总是有帮助的(请参阅)。因此,首先创建一个签名文件,允许您查看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\u func\u与\u r
的结果变量
rresult
识别为
real
。您只需在
my_mod.pyf
中将
real::rresult
替换为所需的
integer::rresult
,执行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

您可以像最初一样一步完成F2PY包装,并且仍然可以获得正确的输出

最后,我将对评论中提出的问题再投一票:当用F2PY包装函数时使用
-fdefault-real-8
会带来麻烦。要执行此操作,F2PY将创建:

一个PythonC/API扩展模块(称为包装器模块) 实现一个Python扩展函数(用C编写,称为 包装器函数),它依次调用给定的Fortran过程


整个过程基于F2PY如何解释Fortran源代码中的数据类型-如果源代码是使用编译器标志编译的,这些标志会更改声明的数据类型,那么最终肯定会出现错误(与原始问题所涉及的
real
/
integer
不匹配直接类似)。因此,变量和函数的数据类型应该在Fortran代码本身中明确设置,请参阅和了解Fortran的
kind
参数,特别是与F2PY相关的参数。

对不起,我无法复制此内容。你能展示一个完整的程序(或多个程序)来说明问题,告诉我们你是如何编译的,你使用的是什么版本的gfortran。嗯,我也不能用纯Fortran来复制它。我使用f2py从Python调用函数,所以这可能就是问题所在。我将稍后发布一个示例。@IanBush,我添加了一个显示问题的程序使用-fdefault-real-8是一个非常愚蠢的主意。-fdefault-real-8是一个坏主意,因为它可能不会做你认为它会做的事情。它违反了Fortran的关联规则,搞砸了
等价性
通用性
、参数传递和其他一些事情。不要用它。最好将代码复制到一个新文件中,并将其从
REAL
正确地移植到
DOUBLE-PRECISION
。在您或其他人质疑我对-default-real-8的理解之前,请查阅它的历史记录!谢谢,这非常有帮助。使用
-fdefault-real-8
有什么危险?指定浮点感知的更好方法是什么?我编辑了我的答案,解释了使用
-fdefault-real-8
的危险,并添加了其他问题/答案的链接,解释了如何在Fortran代码中正确定义浮点精度。
integer function my_func_with_r()
    my_func_with_r = 1
end function