C_FUNLOC
function from the intrinsic module ISO_C_BINDING
accepts a non-interoperable procedure argument.
The C_FUNPTR
value produced should not be converted to a C function pointer, but may be converted to a suitable (also non-interoperable) Fortran procedure pointer with the C_F_PROCPOINTER
subroutine from ISO_C_BINDING
.
For example,
USE ISO_C_BINDING ABSTRACT INTERFACE SUBROUTINE my_callback_interface(arg) CLASS(*) arg END SUBROUTINE END INTERFACE TYPE,BIND(C) :: mycallback TYPE(C_FUNPTR) :: callback END TYPE ... TYPE(mycallback) cb PROCEDURE(my_callback_interface),EXTERNAL :: sub cb%callback = C_FUNLOC(sub) ... PROCEDURE(my_callback_interface),POINTER :: pp CALL C_F_PROCPOINTER(cb%callback,pp) CALL pp(...)
This functionality may be useful in a mixed-language program when the C_FUNPTR value is being stored in a data structure that is manipulated by C code.
C_LOC
function from the intrinsic module ISO_C_BINDING
accepts an array of non-interoperable type,
and the C_F_POINTER
function accepts an array pointer of non-interoperable type.
The array must still be non-polymorphic and contiguous.
This improves interoperability with mixed-language C and Fortran programming, by letting the program pass an opaque “handle” for a non-interoperable array through a C routine or C data structure, and reconstruct the Fortran array pointer later. This kind of usage was previously only possible for scalars.
BIND(C)
routine,
even those with the ALLOCATABLE
or POINTER
attribute.
An assumed-rank argument is passed by reference as a “C descriptor”; it is then up to
the C routine to decode what that means.
The C descriptor, along with several utility functions for manipulating it,
is defined by the source file ISO_Fortran_binding.h
; this can be found
in the compiler's library directory (on Linux this is usually /usr/local/lib/NAG_Fortran
,
but that can be changed at installation time).
This topic is highly complex, and beyond the scope of this document. The reader should direct their attention to the Fortran 2018 standard, or to a good textbook.
TYPE(*)
(“assumed type”) dummy argument is permitted in a BIND(C)
procedure.
It interoperates with a C argument declared as “void *
”.
There is no difference between scalar and assumed-size on the C side, but on the Fortran side,
if the dummy argument is scalar the actual argument must also be scalar,
and if the dummy argument is an array, the actual argument must also be an array.
Because an actual argument can be passed directly to a TYPE(*)
dummy,
the C_LOC
function is not required, and so there is no need for the TARGET
attribute
on the actual argument.
For example,
Program type_star_example Interface Function checksum(scalar,size) Bind(C) Use Iso_C_Binding Type(*) scalar Integer(C_int),Value :: size Integer(C_int) checksum End Function End Interface Type myvec3 Double Precision v(3) End Type Type(myvec3) x Call Random_Number(x%v) Print *,checksum(x,Storage_Size(x)/8) End Program int checksum(void *a,int n) { int i; int res = 0; unsigned char *p = a; for (i=0; i<n; i++) res = 0x3fffffff&((res<<1) + p[i]); return res; }