Turing : Calling Fortran functions from C

Some useful recommendations:

  1. The Fortran 2003 standard has defined a way of interfacing the Fortran procedures with fonctions written in C. We recommend this solution because it both ensures portability and allows any Fortran data types to interoperate with language C types. (For more complete information, refer to Chapter 9 of the Fortran 2003 course: Interoperability between C and Fortran).
  2. Parameter passing in Fortran is done by address, whereas in C it is done by value.
  3. It is recommended to do the linking with the Fortran compiler.

Be aware that if you do not choose the solution of interoperability proposed by Fortran 2003, you will have the following restrictions:

  1. When C activates a Fortran procedure, the arguments furnished during the call must be addresses of objects with a pre-defined type.
  2. As Fortran generates the external references in lower-case letters, this must be respected when making calls in C.

Example of call from C

$ cat appelf.c
#include <stdio.h>
int main ()
{
  int   lg_chaine  = 0;
  float reel       = 0.0;
  char  chaine[]   = "chaîne_C                      ";
 
  lg_chaine = strlen(chaine);
  concat( &amp;lg_chaine, &amp;reel, chaine);
 
  printf("chaîne finale                = %s\n", chaine);
  printf("longueur de la chaîne finale = %d\n", lg_chaine);
  printf("réel passé par adresse       = %f\n", reel);
 
  return 0;
}

Example of definition in Fortran 2003/2008

$ cat concat.f90
module m
  use ISO_C_BINDING
contains
  SUBROUTINE concatenation( lg_chaine, reel, tab_car) bind(C,name='concat')
    INTEGER(kind=C_INT)                          :: lg_chaine
    REAL(kind=C_FLOAT)                           :: reel
    CHARACTER(kind=C_CHAR), dimension(lg_chaine) :: tab_car
    !
    CHARACTER(kind=C_CHAR,len=lg_chaine)         :: chaine
    !write( chaine, '(*(a))' ) tab_car ! Format => Fortran 2008
    ! or
    do i=1,lg_chaine
      chaine(i:i) = tab_car(i)
    end do
    !
    chaine    = TRIM(chaine)//' et chaîne_Fortran'
    lg_chaine = LEN_TRIM(chaine)
    reel      = 100.0
  END SUBROUTINE concatenation
end module m
$ xlc   -c appelf.c
$ xlf90 -c concat.f90
$ xlf90 appelf.o concat.o -o appelc.exe
$ appelc.exe
chaîne finale                = chaîne_C et chaîne_Fortran
longueur de la chaîne finale = 26
réel passé par adresse       = 100.000000

Example of definition in Fortran 90/95

$ cat concat.f90
SUBROUTINE concat( lg_chaine, reel, chaine)
  INTEGER,                  INTENT(INOUT) :: lg_chaine
  REAL,                     INTENT(INOUT) :: reel
  CHARACTER(LEN=lg_chaine), INTENT(INOUT) :: chaine
  chaine    = TRIM(chaine)//' et chaîne_Fortran'
  lg_chaine = LEN_TRIM(chaine)
  reel      = 100.0
END SUBROUTINE concat
$ xlc   -c appelf.c
$ xlf90 -c concat.f90
$ xlf90 appelf.o concat.o -o appelc.exe
$ appelc.exe
chaîne finale                = chaîne_C et chaîne_Fortran
longueur de la chaîne finale = 26
réel passé par adresse       = 100.000000