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