Previous: Interoperable Global Variables, Up: Interoperability with C
Subroutines and functions have to have the BIND(C)
attribute to
be compatible with C. The dummy argument declaration is relatively
straightforward. However, one needs to be careful because C uses
call-by-value by default while Fortran behaves usually similar to
call-by-reference. Furthermore, strings and pointers are handled
differently. Note that only explicit size and assumed-size arrays are
supported but not assumed-shape or allocatable arrays.
To pass a variable by value, use the VALUE
attribute.
Thus the following C prototype
int func(int i, int *j)
matches the Fortran declaration
integer(c_int) function func(i,j) use iso_c_binding, only: c_int integer(c_int), VALUE :: i integer(c_int) :: j
Note that pointer arguments also frequently need the VALUE
attribute.
Strings are handled quite differently in C and Fortran. In C a string
is a NUL
-terminated array of characters while in Fortran each string
has a length associated with it and is thus not terminated (by e.g.
NUL
). For example, if one wants to use the following C function,
#include <stdio.h> void print_C(char *string) /* equivalent: char string[] */ { printf("%s\n", string); }
to print “Hello World” from Fortran, one can call it using
use iso_c_binding, only: C_CHAR, C_NULL_CHAR interface subroutine print_c(string) bind(C, name="print_C") use iso_c_binding, only: c_char character(kind=c_char) :: string(*) end subroutine print_c end interface call print_c(C_CHAR_"Hello World"//C_NULL_CHAR)
As the example shows, one needs to ensure that the
string is NUL
terminated. Additionally, the dummy argument
string of print_C
is a length-one assumed-size
array; using character(len=*)
is not allowed. The example
above uses c_char_"Hello World"
to ensure the string
literal has the right type; typically the default character
kind and c_char
are the same and thus "Hello World"
is equivalent. However, the standard does not guarantee this.
The use of pointers is now illustrated using the C library
function strncpy
, whose prototype is
char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
The function strncpy
copies at most n characters from
string s2 to s1 and returns s1. In the following
example, we ignore the return value:
use iso_c_binding implicit none character(len=30) :: str,str2 interface ! Ignore the return value of strncpy -> subroutine ! "restrict" is always assumed if we do not pass a pointer subroutine strncpy(dest, src, n) bind(C) import character(kind=c_char), intent(out) :: dest(*) character(kind=c_char), intent(in) :: src(*) integer(c_size_t), value, intent(in) :: n end subroutine strncpy end interface str = repeat('X',30) ! Initialize whole string with 'X' call strncpy(str, c_char_"Hello World"//C_NULL_CHAR, & len(c_char_"Hello World",kind=c_size_t)) print '(a)', str ! prints: "Hello WorldXXXXXXXXXXXXXXXXXXX" end
C pointers are represented in Fortran via the special derived type
type(c_ptr)
, with private components. Thus one needs to
use intrinsic conversion procedures to convert from or to C pointers.
For example,
use iso_c_binding type(c_ptr) :: cptr1, cptr2 integer, target :: array(7), scalar integer, pointer :: pa(:), ps cptr1 = c_loc(array(1)) ! The programmer needs to ensure that the ! array is contiguous if required by the C ! procedure cptr2 = c_loc(scalar) call c_f_pointer(cptr2, ps) call c_f_pointer(cptr2, pa, shape=[7])
When converting C to Fortran arrays, the one-dimensional SHAPE
argument
has to be passed. Note: A pointer argument void *
matches
TYPE(C_PTR), VALUE
while TYPE(C_PTR)
matches void **
.
Procedure pointers are handled analogously to pointers; the C type is
TYPE(C_FUNPTR)
and the intrinsic conversion procedures are
C_F_PROC_POINTER
and C_FUNLOC
.
The intrinsic procedures are described in Intrinsic Procedures.