I've asked a few questions on ISO_C_BINDING
, and I made a routine. Since I've always made quite a few mistakes dealing with Fortran POINTER, I want to make it sure that there is no mistake or some weird point that is not a recommended way.
(Fortran part)
program test
use iso_c_binding
implicit none
interface
subroutine get_value_array(in, num) bind(C, name='get_value_Array')
use iso_c_binding
implicit none
type(C_PTR), intent(inout) :: in
integer(C_INT), value, intent(in) :: num
end subroutine
end interface
real(C_DOUBLE), allocatable, target :: array(:)
real(C_DOUBLE), pointer :: array_fptr(:)
type(C_PTR) :: array_cptr
integer :: array_len
allocate(array(12))
array_len = size(array,1)
array_cptr = C_LOC(array)
call get_value_array (array_cptr, array_len)
call C_F_POINTER(array_cptr, array_fptr, [array_len])
print *, 'array_fptr'
print *, array_fptr
print *, 'array'
print *, array
end program
(C part)
void get_value_Array(double **in, int num) {
int i;
for (i = 0; i < num; i++) {
(*in)[i] = i+1;
}
}
(Output)
array_fptr
1.00000000000000 2.00000000000000 3.00000000000000
4.00000000000000 5.00000000000000 6.00000000000000
7.00000000000000 8.00000000000000 9.00000000000000
10.0000000000000 11.0000000000000 12.0000000000000
array
1.00000000000000 2.00000000000000 3.00000000000000
4.00000000000000 5.00000000000000 6.00000000000000
7.00000000000000 8.00000000000000 9.00000000000000
10.0000000000000 11.0000000000000 12.0000000000000
To make it sure, the process is
array_cptr
is associated to array
with C_LOC
function. (Maybe 'associate' is not a proper terminology here since it's Fortran pointer related terminology. What should I call it?)array
gets modified when I call get_value_array
, since the subroutine(or C function) modifies where the array_cptr
points to.array_fptr
is associated to array
through array_cptr
when I call C_F_POINTER
And finally array_cptr
and array_fptr
are different object(?) to each other, while pointing at the same target array
, right?
The statements in the question are ambiguous. To be precise.
With the Fortran statement array_cptr = C_LOC(array)
, array_cptr
is assigned the C address of array
.
When get_value_array
is invoked, the value of array
is ultimately modified by the C function. The Fortran code also makes allowance for the subroutine (or C function) to modify the C address stored in array_cptr
- the dummy argument is declared as INTENT(INOUT) and does not have the VALUE attribute, and consistent with that the C function takes the pointer to the array by reference (i.e. the C formal parameter is declared as a pointer to pointer to double). But the C function does not make such modifications to the C address stored in array_cptr
. For the code shown, there is an unnecessary level of indirection.
The Fortran code associates array_fptr
with the thing referenced by the C address in array_cptr
. Because the C address in array_cptr
has not been been changed by the C function, array_fptr continues to be associated with array
. Execution of C_F_POINTER in this case does not change the state of the program.
array_cptr
is a different thing to array_fptr
- but they have the same target (array_cptr is an object, array_fptr is associated with an object - pointers in Fortran are not objects in their own right, unlike in C).