I'm trying to create a module which has subroutine taking another subroutine's name as argument. Here is a main program (main.for):
program testmod
use action_mod
call main
end program testmod
And here is an example of my module (action_mod.for):
module action_mod
abstract interface
subroutine sub_interface(aA, aB)
integer aA, aB
intent(in) aA
intent(out) aB
end subroutine
end interface
contains
subroutine main
procedure(sub_interface) sub2,sub1
call action(sub1)
call action(sub2)
end subroutine
subroutine action(sub)
procedure(sub_interface) sub
integer argA, argB
argA = 10
call sub(argA, argB)
write(*,*) argA," > ",argB
end subroutine
subroutine sub1(i,o)
integer i,o
o = 100
return
end subroutine sub1
subroutine sub2(i,o)
integer i,o
o = 200
return
end subroutine sub2
end module action_mod
Whe I compile the code with
gfortran -o main action_mod.for main.for
I get an error
/tmp/ccdSM11U.o: In function `__action_mod_MOD_main':
action_mod.for:(.text+0x1a2): undefined reference to `sub1_'
action_mod.for:(.text+0x1b1): undefined reference to `sub2_'
collect2: error: ld returned 1 exit status
But when I put subroutines sub1(i,o) and sub2(i,o) into the main.for everything works fine. However this is not what I want.
Could you help me to find a correct way of creating a module? What is wrong with my code?
You have much the same problem as in this other question, so read answers there for more detail. However, this case has some extra complexity which is worth considering.
In the subroutine main the statement
procedure(sub_interface) sub2,sub1
says that there are external procedures sub2 and sub1. The module subroutines sub1 and sub2 of the module action_mod are not these external procedures. In terms of the linked question, this is like having the declaration character(255) strtok "hiding" the module function strtok.
You should remove that statement from the subroutine.
But you have additional errors to fix. The module subroutines sub1 and sub2 do not have the same interface as the abstract interface sub_interface. You need to ensure that the intent attributes for the dummy arguments of sub1 and sub2, i and o match, those of the sub_interface.
Related
When I have a subroutine outside a module but is used by means of a "pointer assignment" and the subroutine is defined by means of an interface but the real subroutine is in a separate file and used module I get compiler errors.
So when I have the following Fortran code:
module test_mod_a
save
type test_type_a
integer :: scl_a = 0
contains
procedure :: my_subr => test_subr_a
end type test_type_a
interface
subroutine test_subr_a(this)
import test_type_a
implicit none
class(test_type_a) :: this
end subroutine test_subr_a
end interface
end module test_mod_a
and
subroutine test_subr_a(this)
use test_mod_a
implicit none
class(test_type_a) :: this
end subroutine test_subr_a
When I give the commands (gfortran version 9.3.0):
gfortran -c test_a.f90
gfortran -c test_a_subr.f90
I get the compiler error:
test_a_subr.f90:3:6:
3 | use test_mod_a
| 1
Error: ‘test_subr_a’ of module ‘test_mod_a’, imported at (1), is also the name of the current program unit
There are a few ways to overcome this problem:
replace !use test_mod_a by !use test_mod_a, only : test_type_a
include the subroutine in the module (and discarding in the subroutine the use statement and in the module the interface
all a bit cumbersome for a large project.
Is there another way?
As well as the use of only (not including the name of the procedure), there are the two other techniques for avoiding identifier re-use:
private test_subr_a in the module
Use renaming in the subroutine with use test_mod_a, self_iface => test_subr_a
However, from the look of the structure it seems the intention really is for test_subr_a to be like a module subroutine but isn't for one of two reasons:
there's been incremental development of an old program and the external subroutine now wants to be used in a "modern" way
the implementation of the subroutine is split out for reasons of file size, avoiding compilation cascades, secrecy of implementation
With the luxury of changing the code in a significant way one can handle these.
For the first reason, one could go ahead and move the subroutine into the module and take the pain of having to update other references where it was an external subroutine. As mentioned in the question.
For the second reason, submodules could be considered:
module test_mod_a
implicit none
type test_type_a
integer :: scl_a = 0
contains
procedure :: my_subr => test_subr_a
end type test_type_a
interface
module subroutine test_subr_a(this)
class(test_type_a) :: this
end subroutine test_subr_a
end interface
end module test_mod_a
submodule(test_mod_a) implementation_a
implicit none
contains
module subroutine test_subr_a(this)
class(test_type_a) :: this
end subroutine test_subr_a
end submodule implementation_a
Again, test_subr_a is no longer an external subroutine, so other references may need fixing.
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?
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.
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.
I want to allocate an array in a subroutine, and then use this array in the main program and pass it to some other subroutine. In the past (F77?) the passing could be done in a common block, but nowadays the favored procedure seems to be to use a module. When I try this, as in the code example, the compiler tells me
Rank mismatch in argument ‘f’ at (1) (scalar and rank-1)
Apparently, the main program thinks that 'f' is a scalar: but, I read this code to mean that I've declared it as a one-dimensional array, both inside the subroutine and in the main program. What am I missing?
I've tried variations, such as declaring the variables as part of the module, but nothing I could think of made the compilation error-free (and some produced many more errors ;-( ). Any insight is most appreciated.
module subs
contains
subroutine makef(f)
end subroutine makef
end module subs
c-----------------------------------------------------------------------
program work
use subs
implicit none
real, allocatable :: f(:)
call makef(f)
write (*,*) f
stop
end
c---------------------------------------------------------------------
subroutine makef(f)
implicit none
real, allocatable, intent(out) :: f(:)
integer :: i
integer :: is
is=10
allocate(f(-is:is))
do i=-is,is
f(i)=i
end do
return
end subroutine makef
Modules in Fortran are not like header files in other languages which merely provide information about things defined elsewhere. There is the concept of "deferred definition" (submodules) but in this case the module should say everything about the subroutine, not simply attempt to point to its existence.
In the example of the question, we have: the main program; a module subs with module procedure makef; an external subroutine makef.
The main program uses the module subs, and its procedure makef, so reference in the main program to makef is to that module procedure not the external subroutine makef.
The module subroutine makef has the argument f which has no declaration statements, making it an implicitly declared scalar/external function. This is the compiler's message. Use implicit none in modules, just as it's in the main program and external subroutine here.
The entire definition of the subroutine should be placed in the module:
module subs
implicit none
contains
subroutine makef(f)
real, allocatable, intent(out) :: f(:)
integer :: i
integer :: is
is=10
allocate(f(-is:is))
do i=-is,is
f(i)=i
end do
end subroutine makef
end module subs
Alternatively, if one does want to refer to the later implementation of an external procedure an interface block can feature in the module without declaring the subroutine itself. In this case it will still be necessary to specify the complete interface:
module subs
implicit none
! An interface block to give an explicit interface to the external subroutine makef
interface
subroutine makef(f)
implicit none
real, allocatable, intent(out) :: f(:)
end subroutine makef
end interface
end module subs
In this case, don't prefer the interface block.
You only placed the copy of the first and the last line into the module. That can't work. You must move the whole subroutine into the module.
Is it possible in Fortran to define a subroutine within another subroutine? When I try something like
SUBROUTINE test1(...)
! do some stuff
CALL test2(...)
SUBROUTINE test2(...)
! do some stuff
END SUBROUTINE test2
END SUBROUTINE test1.
my compiler (Silverfrost) gives me a recursion error.
As HighPerformanceMark comments, it is possible to define an internal procedure in the contains section of another procedure
SUBROUTINE test1(...)
! do some stuff
CALL test2(...)
CONTAINS
SUBROUTINE test2(...)
! do some stuff
END SUBROUTINE test2
END SUBROUTINE test1
The internal procedure test2 gets access to all entities defined in the host procedure test1 by host association. It also gets access to all entities that test1 has access to. The rules are similar to the rules of internal procedures in the main program.
An internal procedure cannot host another internal procedure.
Procedure pointers to internal procedures are only valid during the execution of the host procedure and are only allowed in Fortran 2008 and later. This is an advanced feature.
This host association can sometimes be annoying, you must be vigilant to avoid bugs like:
SUBROUTINE test1(...)
integer :: i
do i = 1, n
CALL test2(...)
end do
CONTAINS
SUBROUTINE test2(...)
do i = 1, n
!i here is the same variable as i in test1!!
end do
END SUBROUTINE test2
END SUBROUTINE test1
There will be features in Fortran 2015 to change the host association behaviour.
I want to package the fortran interface as a standalone library, something similar head file in c/c++. Here is my code. The problem is that i want to call the "hello" subroutine to run the "hello" subroutine. can anyone help me out?
I want to put Interface and set_callback,invoke_callback as a standalone module file.
MODULE DEMO
INTERFACE
SUBROUTINE callback_prototype(callbackID)
CHARACTER(*) :: callbackID
END SUBROUTINE callback_prototype
END INTERFACE
PROCEDURE( callback_prototype ), POINTER :: f_ptr => NULL()
CONTAINS
SUBROUTINE set_callback(func)
IMPLICIT NONE
EXTERNAL :: func
f_ptr => func
call HELLO
END SUBROUTINE
SUBROUTINE invoke_callback(callbackID)
CHARACTER(*) :: callbackID
if (associated(f_ptr)) call f_ptr(callbackID)
END SUBROUTINE
SUBROUTINE HELLO
IMPLICIT NONE
Dosomething
END SUBROUTINE
END MODULE
This would be easily possible with submodules, unfortunately they are not widely available. Thus, I guess the current solution would be to use "hello" as an external function with an implicit interface and putting it into a different file.
Update: Some example based on your code.
subroutine HELLO
implicit none
write(*,*) 'HELLO'
end subroutine HELLO
module demo
implicit none
interface
subroutine callback_prototype(callbackID)
character(*) :: callbackID
end subroutine callback_prototype
end interface
procedure(callback_prototype), pointer :: f_ptr => NULL()
contains
subroutine set_callback(func)
procedure(callback_prototype) :: func
external :: HELLO
f_ptr => func
call HELLO()
end subroutine set_callback
subroutine invoke_callback(callbackID)
character(*) :: callbackID
if (associated(f_ptr)) call f_ptr(callbackID)
end subroutine invoke_callback
end module demo
program test_demo
use demo
implicit none
write(*,*) 'small program'
end program test_demo
Putting this into a file test.f90, and running "gfortran test.f90" produces an executable. Of course, if you want to have that stuff separated you would rather put each part in separate files. You then have to ensure, that the object file containing "hello" is included during link time. And as pointed out by Vladimir_F, you can use an interface declaration to equip the routine with an explicit interface, where you are calling it.
2nd update:
If you put these into three different files
hello.f90
demo.f90
test.f90
You should be able to compile an executable out of them like this:
gfortran -c demo.f90 hello.f90 test.f90
gfortran *.o
The first line creates the object files, while the second links them together. Note, that order is important, the module information for demo.f90 needs to be available before compiling test.f90.