如何在Fortran中将子例程名称作为参数传递?
作为参数传递子例程名称的语法是什么?示意图:如何在Fortran中将子例程名称作为参数传递?,fortran,subroutine,Fortran,Subroutine,作为参数传递子例程名称的语法是什么?示意图: . . call action ( mySubX ( argA, argB ) ) . . subroutine action ( whichSub ( argA, argB ) ) ... call subroutine whichSub ( argA, argB ) ... end subroutine action 目标是使调用子例程sub argA,argB充当调用子例程mySubX argA,argB。 我的首选
.
.
call action ( mySubX ( argA, argB ) )
.
.
subroutine action ( whichSub ( argA, argB ) )
...
call subroutine whichSub ( argA, argB )
...
end subroutine action
目标是使调用子例程sub argA,argB充当调用子例程mySubX argA,argB。
我的首选是避免传递开关参数,然后使用SELECT CASE。确实如此
call action(mySubX)
如果操作看起来像
subroutine action(sub)
!either - not recommmended, it is old FORTRAN77 style
external sub
!or - recommended
interface
subroutine sub(aA, aB)
integer,intent(...) :: aA, aB
end subroutine
end interface
! NOT BOTH!!
call sub(argA, argB)
假设动作知道将什么放在那里作为argA,argB来代表aA,aB
否则,如果要同时传递参数
call action(mySubX, argA, argB)
subroutine action(sub, argA, argB)
!either - not recommmended, it is old FORTRAN77 style
external sub
!or - recommended
interface
subroutine sub(aA, aB)
integer,intent(...) :: aA, aB
end subroutine
end interface
integer, intent(...) :: argA, argB
call sub(argA, argB)
我不认为在这里使用函数指针是好的,当你不得不改变它指向的子例程的指针值时,它们是好的。正常过程参数在FORTRAN77中有效,即使到现在仍然有效
因此,根据注释中的要求,如果您在一个模块中,并且可以从该模块(可能在同一个模块中)访问具有正确接口的过程,则可以使用procedure语句获取接口块的rod:
module subs_mod
contains
subroutine example_sub(aA, aB)
integer,intent(...) :: aA, aB
!the real example code
end subroutine
end module
module action_mod
contains
subroutine action(sub)
use subs_mod
procedure(example_sub) :: sub
call sub(argA, argB)
end subroutine
end module
但更可能的是,您将创建一个抽象接口,而不是一个真正的子例程,您将使用过程语句引用该接口,因此最终所有内容都将与以前类似:
module action_mod
abstract interface
subroutine sub_interface(aA, aB)
integer,intent(...) :: aA, aB
end subroutine
end interface
contains
subroutine action(sub)
procedure(sub_interface) :: sub
call sub(argA, argB)
end subroutine
end module
我认为使用模块来避免接口是一个很好的现代Fortran实践,因为它提供了一个更干净的接口 以下是实现以下目标的理想方法: 模块部分:
module foo
contains
subroutine callsub(sub,arg1,arg2)
!This subroutine is used to call other subroutines
external::sub !Use external to tell compiler this is indeed a subroutine
call sub(arg1,arg2)
end subroutine
subroutine sub(arg1,arg2)
!The subroutine to be called.
!do something
end sub
end module
下面是主要程序:
program main
use foo !Use module automatically avoids using interface.
implicit none
!Declare about args
call callsub(sub,arg1,arg2)
end program
下面将详细说明如何实现这一点。哪种风格和版本的Fortran?很好的解释。感谢您提供有关语言和函数指针现代用法的提示。我们可以使用模块来消除接口吗?如果可以从某个模块访问某个兼容的过程,您可以使用proceduremySubX::sub。您也可以在模块中为其创建一个抽象接口,并使用相同的procedurenameOfTheInterface。也许我错了,但我的印象是,只有调用方(使用过程参数调用的函数)才需要external关键字,而不是被调用方。否则,根据12.4.2 Fortran 2008,它有一个隐式接口。在5.3.92中:如果外部过程或伪过程用作实际参数或是过程指针赋值的目标,则应声明其具有外部属性。只有在特殊情况下被调用方才必须使用F90+功能。但是,我同意在这种情况下使用抽象接口和模块更好。虽然这在理论上可以回答这个问题,但它会在这里,并提供链接供参考。谢谢纠正我。我是这里的新手,我还在学习礼仪。我添加了更多与问题相关的内容。做得好,这是一个更好的答案,欢迎来到Stackoverflow!这个设计确实消除了对接口块的需要,但是子例程传递的要点是你可以传递任何子例程。现在您在主程序中有了指向sub的显式接口,但在callsub中没有。在现代Fortran中使用proceduresub而不是外部程序会更好。然后你可以在模块中有一个抽象接口,而不是整个子模块。然后你意识到你又在一个接口块上。。。