How to pack fortran interface as a standalone module - fortran

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.

Related

subroutine using module but is outside module and also used in module through an interface

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.

passing allocated array from subroutine to the main program in fortran; use or module? interface?

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.

Access subroutine inside a module using a linked library

I would like to use a subroutine written inside a static library (written in Fortran) inside a different Fortran executables.
This is my working example:
subroutine my(a,b,c)
implicit none
real*8, intent(in) :: a,b
real*8, intent(out) :: c
!
c = a + b
!
end subroutine
That generates a XXX.lib file that I am pointing at with this main:
program main
implicit none
!
real*8 :: var1, var2
real*8 :: out1
!
var1 = 15.0
var2 = 10.0
call mysum(var1,var2,out1)
!
write(*,*) out1
!
end program
Everything is working, but the problem arise when I want to have my subroutine defined inside a module, like this:
module mymodule
contains
!
subroutine mysum(a,b,c)
implicit none
real*8, intent(in) :: a,b
real*8, intent(out) :: c
!
c = a + b
!
end subroutine
end module
At this point the "main" compiler fails in finding the subroutine. Is there a way to let the compiler "see" the subroutine declared inside the module?
Thank you
Simply, if you have a subroutine (or anything else) defined in a module that you want to be made accessible somewhere else you need to "use" that module:
program main
use mymodule
implicit none
....
end program
When you don't have that use mymodule which allows the compiler to see that the subroutine mysum is actually a module subroutine, the compiler is going to treat mysum still as an external subroutine.
Previously, mysum was an external subroutine, but that external subroutine was defined in the library object. It no longer is in the same way: there will likely be various bits of name mangling. It's your linker complaining.

Undefined reference to module subroutines matching an abstract interface

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.

Defining a subroutine in another subroutine

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.