Interoperability with C

25.1 Calling C from Fortran

#include <math.h>
double c_norm(const double *x, int n) {
    double s = 0.0;
    for (int i = 0; i < n; ++i) s += x[i] * x[i];
    return sqrt(s);
}
void c_greet(const char *name) { printf("Hello, %s!\n", name); }
module clib
  use, intrinsic :: iso_c_binding
  implicit none
  interface
    function c_norm(x, n) bind(c, name="c_norm") result(r)
      import :: c_double, c_int
      real(c_double), intent(in) :: x(*)
      integer(c_int), value :: n            ! pass by value
      real(c_double) :: r
    end function c_norm

    subroutine c_greet(name) bind(c, name="c_greet")
      import :: c_char
      character(kind=c_char), intent(in) :: name(*)
    end subroutine c_greet
  end interface
end module clib

program call_c
  use clib
  use, intrinsic :: iso_c_binding
  implicit none
  real(c_double) :: v(3) = [3.0_c_double, 4.0_c_double, 12.0_c_double]
  print *, c_norm(v, 3_c_int)                      ! 13.0
  call c_greet("Fortran" // c_null_char)           ! C strings need a NUL terminator
end program call_c
gcc -c clib.c && gfortran clib.o call_c.f90 -o call_c

25.2 Calling Fortran from C

module flib
  use, intrinsic :: iso_c_binding
  implicit none
contains
  subroutine scale_array(x, n, k) bind(c, name="scale_array")
    integer(c_int), value :: n
    real(c_double), intent(inout) :: x(n)
    real(c_double), value :: k
    x = x * k
  end subroutine scale_array
end module flib
void scale_array(double *x, int n, double k);
int main(void) { double a[3] = {1, 2, 3}; scale_array(a, 3, 2.0); return 0; }

25.3 iso_c_binding essentials

integer(c_long), c_long_long, c_size_t, c_int64_t long, long long, size_t, int64_t real(c_float), real(c_double) float, double double _Complex type(c_ptr), type(c_funptr) void*, function pointer type, bind(c) c_loc(x), c_funloc(f) c_f_pointer(cptr, fptr, shape) convert C pointer to Fortran pointer c_null_ptr, c_null_char NULL, '\0'

25.4 Arrays, strings & memory ownership

Fortran arrays are column-major; C arrays row-major: A(i,j) in Fortran ↔ A[j][i] in C.

Use ISO_Fortran_binding.h (F2018 C descriptors, CFI_cdesc_t) to pass assumed-shape/allocatable arrays to C.

Decide who allocates and frees; don't free Fortran-allocated memory from C or vice versa.

C++: expose functions with extern "C".