Intel® Fortran Compiler Classic and Intel® Fortran Compiler Developer Guide and Reference

ID 767251
Date 6/24/2024
Public

A newer version of this document is available. Customers should click here to go to the newest version.

Document Table of Contents

Standard Fortran and C Interoperability

The Intel® Fortran Compiler supports the Fortran standardized mechanism, allowing Fortran code to communicate (or interoperate) with C code.

This mechanism includes a group of features for C interoperability, enabling mixed-language programming in a more portable manner.

The Fortran standard discusses interoperability in terms of a companion C processor. Each Fortran implementation is free to choose which C is its companion. Although the standard explicitly specifies a companion C (not C++) processor, you can use C++, as long as you use features compatible with C when interoperating with Fortran.

For Intel® Fortran, the supported C companion is the Intel® oneAPI DPC++/C++ Compiler or the Microsoft Visual C++ Compiler on Windows, and the Intel® oneAPI DPC++/C++ Compiler or GCC on Linux.

The core principle of interoperability is that something should work the same way in Fortran as it does in C. In terms of interoperability, the following applies:

  • Fortran references procedures defined by the C programming language or procedures described by C prototypes, even if they are not defined by C.

  • A procedure defined by a Fortran subroutine can be referenced by a function defined by C.

  • You can define global variables associated with C variables whose names have external linkage.

  • You can declare Fortran variables, data structures, and enumerations that correspond to similar declarations in C.

The following sections describe interoperability requirements for types, variables, procedures, and global data.

Example of Fortran Calling C

The following example calls a C function.

C function prototype example:

int C_Library_Function(void* sendbuf, int sendcount, int *recvcounts);

Fortran module example:

module ftn_C_2
   interface 
     integer (C_INT) function C_Library_Function & 
     (sendbuf, sendcount, recvcounts) & 
        BIND(C, name='C_Library_Function')
        use, intrinsic :: ISO_C_BINDING, only: C_PTR, C_INT  
        implicit none 
        type (C_PTR), value :: sendbuf 
        integer (C_INT), value :: sendcount 
        type (C_PTR), value :: recvcounts 
     end function C_Library_Function 
   end interface 
end module ftn_C_2

Fortran calling sequence example:

use, intrinsic :: ISO_C_BINDING, only: C_INT, C_FLOAT, C_LOC
 use ftn_C_2
 implicit none
 ...
 real (C_FLOAT), target :: send(100)
 integer (C_INT) :: sendcount, ret
 integer (C_INT), ALLOCATABLE, target :: recvcounts(:)
 ...
 ALLOCATE( recvcounts(100) )
 ...
 ret = C_Library_Function(C_LOC(send), sendcount, &
                          C_LOC(recvcounts))
 ...

Example of C Calling Fortran

The following example calls a Fortran subroutine called Simulation. This subroutine corresponds to the C void function simulation.

Fortran code example:

subroutine simulation(alpha, beta, gamma, delta, arrays) BIND(C) 
   use, intrinsic :: ISO_C_BINDING 
   implicit none 
   integer (C_LONG), value :: alpha 
   real (C_DOUBLE), intent(inout) :: beta 
   integer (C_LONG), intent(out) :: gamma 
   real (C_DOUBLE),dimension(*),intent(in) :: delta
   type, BIND(C) :: pass 
      integer (C_INT) :: lenc, lenf
      type (C_PTR) :: c, f 
   end type pass 
   type (pass), intent(inout) :: arrays
   real (C_FLOAT), ALLOCATABLE, target, save :: eta(:)
   real (C_FLOAT), pointer :: c_array(:) 
   ... 
   ! Associate c_array with an array allocated in C 
   call C_F_POINTER (arrays%c, c_array, [arrays%lenc] ) 
   ... 
   ! Allocate an array and make it available in C 
   arrays%lenf = 100 
   ALLOCATE (eta(arrays%lenf)) 
   arrays%f = c_loc(eta) 
   ... 
end subroutine simulation

C struct declaration example:

struct pass {int lenc, lenf; float *c, *f;};

C function prototype example:

void simulation(long alpha, double *beta, long *gamma, double delta[], struct pass *arrays);

C calling sequence example:

simulation(alpha, &beta, &gamma, delta, &arrays);