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.
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.
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.
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; }
An absent optional argument of a BIND(C) procedure is indicated by passing a null pointer argument.
For example,
Program optional_example Use Iso_C_Binding Interface Function f(a,b) Bind(C) Import Integer(C_int),Intent(In) :: a Integer(C_int),Intent(In),Optional :: b Integer(C_int) f End Function End Interface Integer(C_int) x,y x = f(3,14) y = f(23) Print *,x,y End Program int f(int *arg1,int *arg2) { int res = *arg1; if (arg2) res += *arg2; return res; }The second reference to f is missing the optional argument b, so a null pointer will be passed for it. This will result in the output:
17 23