Reputation: 635
What is the syntax for passing subroutine names as arguments? Schematically:
.
.
call action ( mySubX ( argA, argB ) )
.
.
subroutine action ( whichSub ( argA, argB ) )
...
call subroutine whichSub ( argA, argB )
...
end subroutine action
The goal is to have call subroutine whichSub ( argA, argB )
act as call subroutine mySubX ( argA, argB )
.
My preference is to avoid avoid passing a switch parameter and then use SELECT CASE.
Upvotes: 7
Views: 9692
Reputation: 60113
It is
call action(mySubX)
provided action looks as
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)
provided action
knows what to put there as argA, argB
to represent aA, aB
.
Otherwise, if you want to pass also the arguments
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)
I don't think it is good to use function pointers here, they are good when you have to change the value of the pointer (the subroutine it points to) sometimes. Normal procedure arguments worked in FORTRAN77 and continue to work even now.
So as requested in the comment, if you are in a module and procedure with the right interface is accessible from the module (perhaps in the same module), you can use the procedure statement to get rod of the interface block:
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
but more likely, instead of a real subroutine you will create an abstract interface which you would reference with the procedure statement so in the end everything will be similar as before:
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
Upvotes: 17
Reputation: 33
I think use module to avoid interface
is a good modern Fortran practice because it gives a cleaner interface.
Here is the ideal the realize that:
module part:
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
Then here is the main program:
program main
use foo !Use module automatically avoids using interface.
implicit none
!Declare about args
call callsub(sub,arg1,arg2)
end program
Here is my demonstration to show exactly how this can be realized.
Upvotes: 2