Let’s have a look at the following example code in C:
/* foo.c */
#include <stdio.h>
void foo_(int *i)
{
printf("%d\n", *i);
}
Using C/Fortran calling conventions, we can invoke routine foo_()
from Fortran without an ISO_C_BINDING interface:
! bar.f90
program main
external :: foo
call foo(42)
end program main
Just building and running the example:
$ gcc -c foo.c
$ gfortran -o bar bar.f90 foo.o
$ ./bar
42
Now say, we introduce a bug and write:
call foo(42.0)
The output will become:
$ ./bar
1109917696
The solution is to declare an interface binding to foo_()
:
program main
use, intrinsic :: iso_c_binding
interface
subroutine c_foo(i) bind(c, name='foo_')
import :: c_int
implicit none
integer(kind=c_int) :: i
end subroutine c_foo
end interface
call c_foo(42)
end program main
The output is the same:
$ gcc -c foo.c
$ gfortran -o bar bar.f90 foo.o
$ ./bar
42
But in contrast, the introduced bug (42.0
) will be detected by the compiler:
$ gfortran -o bar bar.f90 foo.o
bar.f90:12:20:
12 | call c_foo(42.0)
| 1
Error: Type mismatch in argument 'i' at (1); passed REAL(4) to INTEGER(4)
Furthermore, with ISO_C_BINDING interfaces we can pass procedure arguments by value (otherwise, only by reference [1]), and don’t need the trailing underscore in C procedure names. That means, the C code can become:
#include <stdio.h>
void foo(int i)
{
printf("%d\n", i);
}
And the corresponding Fortran interface c_foo()
:
interface
subroutine c_foo(i) bind(c, name='foo')
import :: c_int
implicit none
integer(kind=c_int), intent(in), value :: i
end subroutine c_foo
end interface
[1] If you don’t want to rely on compiler extensions.