我有工作的 Fortran 代码,我试图了解在发出调用语句时使用哪个子例程。
调用语句如下:
CALL get_variable( id_surf, 'building_pars', building_pars_f%pars_xy, &
nxl, nxr, nys, nyn, 0, building_pars_f%np-1 )
但是,没有名称为
get_variable
的子例程。相反,有许多子例程以 get_variable
作为前缀。我在这里只列出了四个:
SUBROUTINE get_variable_2d_real( id, variable_name, var, is, ie, js, je )
SUBROUTINE get_variable_3d_int8( id, variable_name, var, is, ie, js, je, ks, ke )
SUBROUTINE get_variable_3d_real( id, variable_name, var, is, ie, js, je, ks, ke )
SUBROUTINE get_variable_3d_real_dynamic( id, variable_name, var, i1s, i2s, i3s, &
count_1, count_2, count_3, par_access )
所以我的问题是,call语句如何知道要使用哪个子例程?
我所做的是,我使用 grep 通过代码搜索“SUBROUTINE get_variable(”,但没有收到任何结果。
感谢您的提示。确实有一个带有代码的 INTERFACE 块:
INTERFACE get_variable
...
MODULE PROCEDURE get_variable_2d_real
MODULE PROCEDURE get_variable_3d_int8
MODULE PROCEDURE get_variable_3d_real
MODULE PROCEDURE get_variable_3d_real_dynamic
...
END INTERFACE get_variable
所以,CALL get_variable 指的是接口,然后根据参数及其类型,使用过程之一,这是正确的吗?
Fortran 中对事物的引用必须包含(全)名称。这适用于变量、过程(函数和子例程)、类型、模块等。前缀永远不会“完成”,以扩展名称的较短形式。
您已经确定了
get_variable
子例程的特定情况来源:它是一个通用的,由接口块给出。我不会详细介绍如何将对通用子例程的引用解析为特定子例程:当术语已知时,可以找到大量信息。简而言之,编译器使用与参数相关的严格规则来计算出哪些特定子例程。它从接口块中明确指定的(明确的)列表中进行选择;它不会检查共享给定前缀的所有子例程。
我要解决的是通过源代码搜索找不到子程序失败的问题。
看到该名称是由 INTERFACE 语句给出的,这表明
subroutine sub(
不是一个合适的搜索词。如果您认为interface sub
可以找到所有subroutine sub(
未找到的案例,那么接下来的故事就是一个悲伤的故事。
具有隐式接口的子例程不需要声明:
call sub
end
(这是一个外部子例程,可以在链接时解析;它甚至可能是一个非 Fortran 子例程。)
子例程可能位于您看不到源代码的模块中:
use fortran_tool ! , only : sub
call sub
end
有类似的过程声明语句
procedure() sub
call sub
end
还有虚拟过程和过程指针,其中
sub
甚至不需要是链接时将解析的对象的名称。
甚至在我们遇到类似的恐怖之前
subroutine & ! My crazy style guide says to put the name on a new line
sub &
()
和
sub routine
C Here it comes
1s
2u
C still coming
3b
最终,值得研究一种能够理解 Fortran 语言的源代码分析工具(grep 不是其中之一)。但是,我不会推荐或命名任何内容。