A dummy argument in a Fortran procedure with the BIND(C)
attribute that doesn't have the VALUE argument is equivalent on the C side to a pointer parameter (this is broadly consistent with the usual Fortran convention of things being passed by reference). So if on the Fortran side you have INTEGER(C_INT) :: a
(no value attribute), that's equivalent on the C side to int *a
.
Perhaps that's obvious, but it has a surprising consequence - if you have TYPE(C_PTR) :: p
, that's equivalent to void **p
- a C_PTR is a pointer, so a C_PTR passed without value is a pointer to a pointer. Given this, your interface for the callback is out (you need to add VALUE
).
The interoperable analogue in a type sense to a C pointer to a function (which is what a function name sans parentheses is in C) in Fortran is a TYPE(C_FUNPTR)
. The same considerations with respect to the absence of the VALUE attribute and C_PTR
apply - an argument declared TYPE(C_FUNPTR) :: f
is a pointer to a pointer to a function. Given this and your C side call of the Fortran, the argument corresponding to the function pointer should have the VALUE
attribute.
The fact that a Fortran procedure pointer happens to work is just a (not terribly surprising) coincidence of the underlying implementation of C function pointers and Fortran procedure pointers, and the way that Fortran procedure pointers are passed.
All up, your Fortran procedure probably needs to have an interface that looks like:
integer(c_int) fortran_function(n, image, callback, c_object) &
bind(c, name='fortran_function')
integer(c_int), value :: n
integer(c_signed_char), intent(inout), dimension(n) :: image
type(c_funptr), intent(in), value :: callback
type(c_ptr), intent(in), value :: c_object
(your declaration of the image array in your original code seems astray - perhaps the above is appropriate, perhaps not)
and your declaration of the interface of the C callback needs to have an interface of:
abstract interface
subroutine c_callback(c_object) bind(c)
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr), intent(in), value :: c_object
end subroutine c_callback
end interface
(As discussed on the Intel fora over the last few months (where have you been?), current ifort may have a problem with it's handling of C_PTR
and VALUE
.)