Reputation: 1435
I have a large source code where subroutines in modules are defined outside the module ... end module
statement (ie. not inside a contains
statement). I've included a simplified module below:
module core
implicit none
type :: disc_status
sequence
real*8 :: alpha1, alpha2, alpha3
end type disc_status
end module core
subroutine tester(input)
use core
type(disc_status), intent(in) :: input
print *, input%alpha1, input%alpha2, input%alpha3
end subroutine tester
Here's an example program using the module and subroutine:
program flyingDiscSimulator
use core
implicit none
type(disc_status) :: disc
disc%alpha1 = 1.1D0
disc%alpha2 = 1.2D0
disc%alpha3 = 1.3D0
call tester(disc)
print *, 'it works'
end program flyingDiscSimulator
Normally, I end up seeing subroutines use the contains
statement within a module:
module core
implicit none
type :: disc_status
sequence
real*8 :: alpha1, alpha2, alpha3
end type disc_status
contains
subroutine tester(input)
type(disc_status), intent(in) :: input
print *, input%alpha1, input%alpha2, input%alpha3
end subroutine tester
end module core
However, the program file referenced above doesn't require any changes to use either way of including a subroutine in a module (using gfortran anyways). Thus, there appears to be no difference in the usage of the module or it's subroutine between the two solutions. Are there any "under the hood" differences between the two styles?
Upvotes: 3
Views: 509
Reputation: 32431
The versions
module m
contains
subroutine s()
end subroutine s
end module m
and
module m
end module m
subroutine s()
end subroutine s
say completely different things, but in the case of the question the end results are much the same.
The first version here creates a module procedure s
with host m
; the second version has an external procedure s
with no host.
Although the example of the question has the external procedure using the module, there is more generally a difference: the module procedure has access to all entities in the module (except when made inaccessible through an import
statement or by being obscured by local names; the external procedure using the module has access only to those public entities.
However, come the main program the effects are different. The external subroutine and its name are global entities. Going to my second version, then
program main
call s
end program
is a valid program which calls the external subroutine s
. This subroutine reference is valid because the implicit interface for s
in the main program suffices. If the external subroutine s
were such than an explicit interface were required then main program here would not be allowed. It is acceptable, but not required, to have an external s
statement in the main program to reinforce to the reader that the subroutine is an external one (with implicit interface). (implicit none external
would make external s
necessary.)
The example of the question is such that an explicit interface is not required.
A module procedure always has an explicit interface available when accessible. However, a module procedure is not a global entity and its name is not a global identifier.
Under the hood, there are implementation differences (stemming from the above): most notably compilers will often "name mangle" module procedures.
In summary, there are differences between the two approaches of the question, but they won't be noticed by the programmer in this case.
Upvotes: 4
Reputation: 1790
The procedure inside the module will have an explicit interface (aka the compiler knows about the arguments' characteristics). Whereas the procedure outside of the module will have an implicit interface (aka the compiler must make assumptions about the arguments).
Explicit interfaces help the compiler to find programming errors and are therefore favourable. For a more indepth discussion of advantages see for example this answer.
I am not even sure if it is valid Fortran to call tester
inside the program when it is defined outside of core
?
The line use core
should just make the module's public objects known and the tester procedure needs its own external tester
line.
Upvotes: 0