Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling FORTRAN function from C wrapper

I am a newcomer to this, but I need to access some old Fortran 77 functions from C. I don't want to alter the Fortran code if possible, I would really prefer to write a wrapper to call the Fortran functions from C. I hope to get a minimal working example (on Linux). What I did:

In file somefunction.f:

REAL*8 FUNCTION MYFUNC(ZZ)
      IMPLICIT NONE
      REAL*8 ZZ, T1
      T1 = ZZ + 1.0D0
      MYFUNC = T1
      RETURN
      END

compiled with gfortran -c somefunction.f -o somefunction.o.

In file debug.c:

#include <stdio.h>

double cfunc(double x) {
    double result = myfunc_( &x );
    return result;
}
int main() {
    double test = cfunc(3.0);
    printf(" %.15f ",test);
}

compiled with gcc -c debug.c -o debug.o.

Then I give gcc debug.o somefunction.o and ./a.out.

However, instead of 3+1=4, I get nonsensical numbers. How do I correct this?


P.S: If this is solved, the actual functions I have are a bit more complicated:

  1. What should I change if MYFUNC were to be instead of the type COMPLEX*16 FUNCTION MYFUNC(ZZ) with ZZ also a complex?

  2. What if MYFUNC called some built-in Fortran function, say CDLOG(ZZ) ?

  3. And what if it accesses a common block? Can this be accommodated too?

like image 775
Marco Avatar asked Jun 10 '26 02:06

Marco


1 Answers

In addition to the return type, you also need to pay attention to the way the Fortran procedure name is mangled into a symbol that you access from C. There's no standard, it entirely depends on the Fortran compiler and platform, so you'll have to use some configure-time detection and a macro if you want portability.

For example, Fortran MYFUNC() needs to be called from C as:

  • MYFUNC() under Intel Fortran on Windows
  • myfunc() under IBM XL Fortran (xlf)
  • myfunc_() in most other cases (including GNU Fortran on Windows)

(It gets even more complicated when the Fortran routine is in a module, because then the mangled name is prefixed by the module and _MOD_, _mp_, etc.)

The modern Fortran solution is to declare a bind(C) routine on the Fortran side, which turns this mangling off (or you can specify an explicit binding name).

like image 122
TooTea Avatar answered Jun 11 '26 15:06

TooTea



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!