问题
I am struggling with explicit interfaces in Fortran.
In one instance, the compiler has requested that I write an explicit interface when I attempt to use an assumed-shape array as a dummy argument for a function or subroutine (i.e., procedure): Explicit interface required for ... assumed-shape argument
. For example, this would appear like REAL, INTENT(IN OUT) :: dummy_array(:)
in a subroutine. The (:)
in the declaration of the array means that the compiler takes care of passing information about the shape of the array to the subroutine. That's handy, but it also means that the compiler must know to do this when compiling the call or reference to the procedure. This is not evident from the CALL
(or reference) alone, so the compiler must have information about the procedure's dummy arguments, hence the need for a explicit interface.
From what I understand, there are three methods for implementing an explicit interface in Fortran:
- Use a
MODULE
thatCONTAINS
the procedure. This tends to be the recommended approach. - Make the procedure internal to whatever calls it. This would be like putting a
CONTAINS
statement right before theEND
statement of my main program. The entire code of my procedure would then be placed between these two statements. - Write an
INTERFACE
for the procedure. I guess most folks default to this, but it tends to be the least recommended approach as it can be a bit laborious.
This brings me to my current problem: In another instance, the compiler gives Explicit interface required for ... allocatable argument
. Here are the relevant parts following method 1 above:
MODULE My_Module
CONTAINS
SUBROUTINE Clean(my_array_sizes, my_arrays, my_arrays_clean)
USE Shared, ONLY : dp
IMPLICIT NONE
...
REAL(dp), INTENT(OUT), ALLOCATABLE, ASYNCHRONOUS :: my_arrays_clean(:)
...
ALLOCATE(my_arrays_clean(non_zero)) !new array of correct size
my_arrays_clean = temp(1:non_zero) !transfer values
END SUBROUTINE Clean
END MODULE My_Module
The problem seems to be with the dummy array my_arrays_clean
. Here's the call:
CALL Clean(my_array_size, probability, probability_clean) !remove empty values from array
The declaration of probability_clean
:
REAL(dp), DIMENSION(:), ALLOCATABLE, ASYNCHRONOUS :: probability, probability_clean !store Photon(E_i, depth) values
All seems well until I try to compile with gfortran -g -std=f2008 -Wall -Wextra -O2 -fall-intrinsics -fopenmp
: undefined reference to 'clean_'
. I have no idea what's wrong. Of course I can work around this problem to accomplish what I need, but I'd really like to understand the proper way to do this.
回答1:
When we talk about an explicit (or implicit) interface, we aren't talking about a property of the procedure itself. A procedure has an interface, but this is not entirely the same concept. Take the module and subroutine as below.
module mod
contains
subroutine sub
end subroutine
end module
The subroutine sub
has an interface, including such information as it being a subroutine called sub
with no dummy arguments. The subroutine of interest from the question has its own corresponding interface.
The "explicit interface" instead is about what information is known about the procedure's interface at the point at which the procedure is referenced. Look at
call sub
end
and compare it with
use mod, only : sub
call sub
end
In the first case, without using the module mod
the compiler can't even see sub
as being the subroutine within the module. sub
here is an external procedure with implicit interface (and not the one in the module). In the second, sub
is use associated; not only does the compiler now see the module subroutine but it sees the interface (which is now explicit).
Likewise, an internal procedure (item 2. using the contains
statement) always has an explicit interface in its host:
call sub
contains
subroutine sub
end subroutine
end program
Third, with an interface block:
subroutine sub
end subroutine
interface
subroutine sub
end subroutine
end interface
call sub
end program
In conclusion: accessible module procedures always have an explicit interface available, but they must first be made accessible with a use
statement. Internal procedures are always accessible in the host, always with an explicit interface. Interface blocks provide an explicit interface, but again the interface block itself must be around where the procedure reference is made.
来源:https://stackoverflow.com/questions/55270873/correct-implementation-of-an-explicit-interface-in-fortran