Interface between a Fortran77 program and a Fortran90 program

In summary, you would use a module to create an interface between two independent programs. When one of the programs is f77, the usual approach is to create libraries out of the code with functions that your main program can call.
  • #1
davidfur
18
2
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
 
Technology news on Phys.org
  • #3
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?
 
  • #4
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/M...ojects/bldaps_for/ug1l_create_shared_libs.htm

https://shocksolution.com/2009/10/26/building-and-linking-to-a-shared-fortran-library/
 
  • #5
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.
 
  • Like
Likes jedishrfu
  • #6
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:
  • #7
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.
 
  • #8
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.
 
  • #9
The subroutine double_coords(x,y,z) doesn't have access to the variable dbl that is part of the module my_mod.
 
  • #10
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
 
  • #11
davidfur said:
and why's that?
You have to add use my_mod in the subroutine.
 
  • #12
DrClaude said:
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.
 
  • #13
Perhaps an output listing might help ? (screenshot, if that's where the "write"s are going to). Any compiler Warnings/Errors ?
 
  • #14
davidfur said:
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.
 
  • #15
DrClaude said:
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:
  • Like
Likes DrClaude

FAQ: Interface between a Fortran77 program and a Fortran90 program

How can I make my Fortran77 program compatible with a Fortran90 program?

In order to make your Fortran77 program compatible with a Fortran90 program, you will need to make sure that your Fortran77 code follows the Fortran90 standards. This includes using the appropriate syntax, such as using "end do" instead of "continue", and updating any outdated functions or features that are not supported in Fortran90. Additionally, you may need to use a compiler that supports both Fortran77 and Fortran90.

Can I use modules in both my Fortran77 and Fortran90 programs?

Yes, both Fortran77 and Fortran90 support the use of modules. However, it is important to note that the syntax for modules is slightly different between the two versions. For example, in Fortran77, modules are declared with the "module" statement, whereas in Fortran90, the "module" statement is followed by the "end module" statement.

Is it possible to call a Fortran77 subroutine from a Fortran90 program?

Yes, it is possible to call a Fortran77 subroutine from a Fortran90 program. However, there are a few things to keep in mind. Firstly, the Fortran77 subroutine must be declared with the "external" statement in the Fortran90 program. Additionally, the arguments passed to the subroutine must be compatible between the two programs, meaning they must have the same data type and size.

How can I share variables between my Fortran77 and Fortran90 programs?

The most common way to share variables between Fortran77 and Fortran90 programs is by using the "common" statement. This allows the programs to access shared variables, as long as they are declared in the same way in both programs. However, it is important to note that the "common" statement is not supported in all compilers, so it is best to check your compiler's documentation before using it.

Are there any compatibility issues when using Fortran77 and Fortran90 together?

While Fortran77 and Fortran90 are both versions of the Fortran programming language, there are some compatibility issues that may arise when using them together. These include differences in syntax and features, as well as the potential for errors when passing variables between the two programs. It is important to carefully check your code and use a compiler that supports both versions to avoid any issues.

Similar threads

Replies
1
Views
3K
Replies
16
Views
2K
Replies
2
Views
3K
Replies
5
Views
4K
Replies
4
Views
2K
Back
Top