Fortran Interface between a Fortran77 program and a Fortran90 program

  • Thread starter davidfur
  • Start date
12
1
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
 
10,953
4,456
12
1
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?
 
10,953
4,456
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.

It also speeds compiling, linking and loading of the program. Compiling because they are only compiled when changed not hen your program code changes. Linking because less code is added to your executable and loading because if the shared library is already loaded in memory it will be used.

Some references:

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

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

https://shocksolution.com/2009/10/26/building-and-linking-to-a-shared-fortran-library/
 

DrClaude

Mentor
6,972
3,145
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.
 
12
1
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:
10,953
4,456
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.
 
10,953
4,456
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.
 

DrClaude

Mentor
6,972
3,145
The subroutine double_coords(x,y,z) doesn't have access to the variable dbl that is part of the module my_mod.
 
12
1
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
 
12
1
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.
 
275
78
Perhaps an output listing might help ? (screenshot, if that's where the "write"s are going to). Any compiler Warnings/Errors ?
 

DrClaude

Mentor
6,972
3,145
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.
 
12
1
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:

Want to reply to this thread?

"Interface between a Fortran77 program and a Fortran90 program" You must log in or register to reply here.

Related Threads for: Interface between a Fortran77 program and a Fortran90 program

Replies
3
Views
2K
Replies
5
Views
4K
Replies
5
Views
2K
Replies
9
Views
768
Replies
5
Views
3K
  • Posted
Replies
4
Views
5K
Replies
4
Views
3K

Physics Forums Values

We Value Quality
• Topics based on mainstream science
• Proper English grammar and spelling
We Value Civility
• Positive and compassionate attitudes
• Patience while debating
We Value Productivity
• Disciplined to remain on-topic
• Recognition of own weaknesses
• Solo and co-op problem solving
Top