Can an f77 subroutine be called from C?

135 views Asked by At

In modern Fortran, we can call a subroutine from C by using C binding. E.g. The Fortran subroutine will look like this

subroutine my_routine(...) bind (C, name="my_routine")

However, if the fortran subroutine is an old f77 subroutine, this binding is presumably not an available solution. What would be the best alternative?

2

There are 2 answers

1
John Bollinger On BEST ANSWER

However, if the fortran subroutine is an old f77 subroutine, this binding is presumably not an available solution.

It depends. Modern Fortran is largely backwards compatible with Fortran 77. Your F77 subroutine will not come with a bind attribute, but if you're willing to add one and compile it with a modern Fortran compiler then chances are pretty good that it will work just as you expect of code originally written for a newer Fortran version.

On the other hand, what C interop brings to Fortran is standardization, not a new capability. People have been calling Fortran routines from C almost as long as people have been using C.

The issue here is that the specifics are system and compiler dependent. If you don't rely on C interop, then you will need to accommodate your Fortran compiler's name-mangling and argument-passing conventions to successfully call Fortran-compiled functions from C code. These vary. There used to be a fair amount of tools and documentation for such activity. I imagine it's harder to find these days, but much of it should still work.

What would be the best alternative?

That depends on your specific constraints. If you're up for modifying the Fortran source and compiling with a modern compiler then I'd at least start with adding a bind attribute to the function, and see how that plays out.

1
Vladimir F Героям слава On

Remember that you are likely compiling the code as Fortran 2003-2018 anyway, if you are using any reasonably recent compiler. Even discontinued compilers like g95 already had the C-Fortran interop from Fortran 2003.

However, as I also commented under John's answer, if you do add bind(C) to it, the existing Fortran calls (as an external subroutine without explicit interface) to the subroutine will be invalid. They may work in practice, but won't for character strings, for example. And even if they would work, they would not be standard conforming. That only matters if you care about the existing calls to the subroutine from Fortran.

If you could not touch the code at all - if the source code must remain intact for some reason. You can always write a wrapper subroutine that does use bind(C) and that calls the original subroutine. Usually that is not unnecessary, but it is a possibility.

As John Bollinger mentions, there are ways how to call the Fortran subroutines without bind(C) in a system specific way, discussed in several questions on this site. The symbol name would typically have an underscore appended (most likely) or prepended, or both.Two underscores are also a possibility. The symbol name might use either small caps or capital letters. The arguments would be passed by reference (through a pointer). Character strings character(*) would use a hidden integer argument containing the length of each string.