# Interface between a Fortran77 program and a Fortran90 program

• Fortran
davidfur
Hi all,
I'm new to Fortran programming, so I might probably ask some really trivial questions - please forgive me.
I have two source codes of big programs. One is coded in Fortran77 and the other one in Fortran90.
Now, I need to build an interface so that the Fortran90 program can call some subroutines/functions in the Fortran77 program.

Now, I know that usually you would use a module for that purpose: just put all the subroutines and functions you want inside the module, and call it from your main program.
However, in my case, the two programs are very big and spread across many files and obviously there are two "program units. Does that change anything? If so, how?

In general, what would you suggest be the best way of building such an interface between the two?

Cheers,
Dave

## Answers and Replies

davidfur
Hi jedishrfu
Thanks for your answer! That's probably a good idea, I'll look into the links you provided. So, in your opinion what would be a good strategy for this kind of interface? i.e. building in interface between two independent programs (suppose they are both f90) ?

And, what about when one of then is f77?

Mentor
Well the usual approach is to create libraries out of the code with functions that your main program can call.

The prevailing strategy is to make them shared libraries but they could be static libraries if used by your one program alone or seldom used. Shared libraries reduces the memory footprint of multiple programs running all using the same code in the shared libraries.

Some references:

http://astroa.physics.metu.edu.tr/MANUALS/intel_ifc/mergedProjects/bldaps_for/creating_libraries.htm

http://astroa.physics.metu.edu.tr/M...ojects/bldaps_for/ug1l_create_shared_libs.htm

Mentor
If the Fortran 77 subroutines are self-standing, meaning that there is no need for common blocks in the calling code, then it is trivial. Simply keep the F77 code in a separate file that is compiled by itself into an object file, and link that with the main code written in F90.

I have some code where he reverse is done: I have written additional subroutines in F90, and I call them from the F77 code as if they were F77 routines. The Fortran compilers (I use mainly gcc and the Intel compiler) have no problem with that.

jedishrfu
davidfur
Right. First of all, I converted all the f77 sources to f90 sources with f2f (https://bitbucket.org/lemonlab/f2f/). Now to the actual interface part.

Just to begin to understand how these things work, I've built three example files (main.f90, my_mod.f90 and my_sub.f90). Let's suppose that my_sub.f90 is the subroutine in program1, main.f90 is program2 and my_mod.f90 is the module that connects them (program2 needs some output from program1 based on some input).

I'm trying to pass some output from my_sub.f90 into my_mod.f90 and then use this module in main.f90.

But - I encounter a problem. The variables dbl(1:3) come out as 0.000000, instead of their respective values (6.0, 8.0, 10.0).

Could anybody point me to my mistake?

edit: forgot to add my compilation instructions. Here they are:
Bash:
gfortran -c my_sub.f90
ar -rcs libmysub.a my_sub.o
gfortran -c my_mod.f90 -L./ -lmysub
gfortran -c main.f90
gfortran my_mod.o main.o -o main -L./ -lmysub
main.f90
Code:
program main

use my_mod
implicit none

!real :: dbl(1:3)

real xx, yy, zz

write (*,*) "I'm in main"

xx = 3.0
yy = 4.0
zz = 5.0

call get_coords(xx,yy,zz)
write (*,*) "output coords:",dbl(1), dbl(2), dbl(3)

end program main

my_mod.f90
Code:
module my_mod
implicit none
! declare variables
real dbl(3)

contains
! define subroutines or functions

subroutine get_coords(x,y,z)

real  :: x, y, z
!real :: dbl(1:3)

write (*,*) "I'm in my_mod. input coords: ",x,y,z
call double_coords(x,y,z)

end subroutine get_coords

end module my_mod

my_sub.f90 in the mysub library:
Code:
subroutine double_coords(x,y,z)
real :: x,y,z
real dbl(3)

dbl(1) = 2.0*x
dbl(2) = 2.0*y
dbl(3) = 2.0*z
!write (*,*) "I'm in mysub: double_coords. dbls are: ", dbl(1), dbl(2), dbl(3)
end subroutine double_coords

editted and reorganized by mentor for clarity -- jedi

Last edited by a moderator:
Mentor
Off hand I don't see why they are wrong. Sometimes this occurs when you've defined the vars in the calling program as one type say double but defined them as another type say float in the subroutine. That causes a memory alignment issue where 8 bytes of a double is being looked as a 4 byte float.

I saw this occur once when a library was built with a flag to indicate that floats were to begin on eight byte boundaries but the program using the library was not.

https://en.wikipedia.org/wiki/Data_structure_alignment

I throw this out there for you, however I don't think that's the issue here based on your gfortran commands.

Have you tried having the main call the double _coords directly? They are still in separate files with one in a separate library right?

Also are you familiar with using a the gdb debugger? Its good to learn it as it can help to isolate these types of problems. As an example, you might see the arguments coming in aligned one way and the subroutine is reading them a different way.

Mentor
I adjusted your post to make it more readable, breaking up the paragraph of text and reordering the program listings to make it easier to follow ie main-->get_coords-->double_coords execution sequence and adding some commentary about the subroutine in the library.

Mentor
The subroutine double_coords(x,y,z) doesn't have access to the variable dbl that is part of the module my_mod.

davidfur
DrClaude: and why's that? Do i need to write an INTERFACE statement in the beginning of my_mod to make the subroutine access the module variable dbl?

jedishrfu: I also tried calling double_coords directly from main.f90, but still all I see is 0.0000, 0.0000, 0.0000

Mentor
and why's that?
You have to add use my_mod in the subroutine.

davidfur
You have to add use my_mod in the subroutine.

If that is the reason, then it's a bit weird...because I did include use my_mod in main.f90, and directly calling double_coords didn't work either. Returned same answer as with the my_mod route.

Gold Member
Perhaps an output listing might help ? (screenshot, if that's where the "write"s are going to). Any compiler Warnings/Errors ?

Mentor
If that is the reason, then it's a bit weird...because I did include use my_mod in main.f90, and directly calling double_coords didn't work either. Returned same answer as with the my_mod route.
I don't understand what you mean.

double_coords is a self-standing subroutine. As such, it only has access to its local variables and to the arguments passed to it (which is always pass by reference in Fortran). Hence, the dbl inside double_coords is a local variable, which has no link to the dbl variable found in the module my_mod. The fact that the two variables have to same name is completely irrelevant.

So, either instruct the subroutine double_coords to use my_mod, in order for it to be able to modify the variable dbl found in that module, or you add an argument to double_coords such that it returns the modified value through an argument. For a self-standing variable, the latter method is preferable; it then acts like any library routine, with input and out processed through arguments.

davidfur
I don't understand what you mean.

double_coords is a self-standing subroutine. As such, it only has access to its local variables and to the arguments passed to it (which is always pass by reference in Fortran). Hence, the dbl inside double_coords is a local variable, which has no link to the dbl variable found in the module my_mod. The fact that the two variables have to same name is completely irrelevant.

So, either instruct the subroutine double_coords to use my_mod, in order for it to be able to modify the variable dbl found in that module, or you add an argument to double_coords such that it returns the modified value through an argument. For a self-standing variable, the latter method is preferable; it then acts like any library routine, with input and out processed through arguments.

DrClaude: Thanks! following your words, I now understand what I was doing wrong. The trouble was that I was using the dbl variable inside my_sub as if it was passed by reference from the module (without adding use my_mod). When I did add use my_mod to my_sub, and removed the declaration of dbl, it worked! namely, the values passed to the module, then from the module to the main. But, I don't want to actually change anything inside my_sub and only interested in passing variables from my_sub as arguments.

So, I've tried to pass the variables from my_sub to my_mod via the argument: I removed the declaration of dbl(3) in my_sub, and just assigned the new values of x,y,z into x,y,z themselves. Then, in my_mod I assigned the values of x,y,z coming from my_sub into dbl(1),dbl(2),dbl(3). This also worked and now the variables are printed in main as needed!

Thank you all guys for helping! Just for future reference and people that might stumble in a similar problem, I attach the new, working sources.

Code:
gfortran -c my_mod.f90
gfortran -c my_sub.f90
ar -rcs libmysub.a my_sub.o
gfortran -c main.f90
gfortran my_mod.o my_sub.o main.o -o main -L./ -lmysub

Code:
program main

use my_mod
implicit none

!real :: dbl(1:3)

real xx, yy, zz

write (*,*) "I'm in main"

xx = 3.0
yy = 4.0
zz = 5.0

call get_coords(xx,yy,zz)
!call double_coords(xx,yy,zz)

write (*,*) "output coords:",dbl(1), dbl(2), dbl(3)

end program main

Code:
module my_mod
implicit none
! declare variables
real dbl(3)

contains
! define subroutines or functions

subroutine get_coords(x,y,z)

real  :: x, y, z
!real :: dbl(1:3)

write (*,*) "I'm in my_mod. input coords: ",x,y,z
call double_coords(x,y,z)
dbl(1) = x
dbl(2) = y
dbl(3) = z

end subroutine get_coords

end module my_mod

Code:
subroutine double_coords(x,y,z)
!use my_mod
real :: x,y,z
!real dbl(3)

x = 2.0*x
y = 2.0*y
z = 2.0*z
!write (*,*) "I'm in mysub: double_coords. dbls are: ", dbl(1), dbl(2), dbl(3)
end subroutine double_coords

Last edited:
DrClaude