7.1.5 Работа с указателями
Указатели C в Фортране представлены с помощью специального неявного производного типа type(c_ptr) (с закрытыми компонентами). Поэтому для преобразования в указатели C или из них необходимо использовать встроенные процедуры преобразования.
В некоторых приложениях использование типа с предполагаемым типом (TYPE(*)) может быть альтернативой указателю C; см. Дополнительная взаимосвязь Фортрана и C.
Например,
use iso_c_binding
type(c_ptr) :: cptr1, cptr2
integer, target :: array(7), scalar
integer, pointer :: pa(:), ps
cptr1 = c_loc(array(1)) ! The programmer needs to ensure that the
! array is contiguous if required by the C
! procedure
cptr2 = c_loc(scalar)
call c_f_pointer(cptr2, ps)
call c_f_pointer(cptr2, pa, shape=[7]) При преобразовании массивов C в Фортран необходимо передавать одномерный SHAPE аргумент.
Если указатель является аргументом-заглушкой интерпретируемой процедуры, обычно требуется объявление с атрибутом VALUE. void* соответствует TYPE(C_PTR), VALUE, в то время как TYPE(C_PTR) соответствует void**.
Указатели процедур обрабатываются аналогично указателям; тип C – TYPE(C_FUNPTR), а встроенные процедуры преобразования – C_F_PROCPOINTER и C_FUNLOC.
Рассмотрим два примера передачи указателя процедуры из C в Фортран и наоборот. Обратите внимание, что эти примеры также очень похожи на передачу обычных указателей между этими двумя языками. Сначала рассмотрим этот код на C:
/* Procedure implemented in Fortran. */
void get_values (void (*)(double));
/* Call-back routine we want called from Fortran. */
void
print_it (double x)
{
printf ("Number is %f.\n", x);
}
/* Call Fortran routine and pass call-back to it. */
void
foobar ()
{
get_values (&print_it);
} Соответствующая реализация для get_values на Фортране, которая правильно получает указатель на процедуру из C и может ее вызвать, приведена в следующем MODULE:
MODULE m
IMPLICIT NONE
! Define interface of call-back routine.
ABSTRACT INTERFACE
SUBROUTINE callback (x)
USE, INTRINSIC :: ISO_C_BINDING
REAL(KIND=C_DOUBLE), INTENT(IN), VALUE :: x
END SUBROUTINE callback
END INTERFACE
CONTAINS
! Define C-bound procedure.
SUBROUTINE get_values (cproc) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
TYPE(C_FUNPTR), INTENT(IN), VALUE :: cproc
PROCEDURE(callback), POINTER :: proc
! Convert C to Fortran procedure pointer.
CALL C_F_PROCPOINTER (cproc, proc)
! Call it.
CALL proc (1.0_C_DOUBLE)
CALL proc (-42.0_C_DOUBLE)
CALL proc (18.12_C_DOUBLE)
END SUBROUTINE get_values
END MODULE m Далее мы хотим вызвать процедуру C, которая ожидает указатель на процедуру в качестве аргумента, и передать ей процедуру Фортрана (которая, очевидно, должна быть совместимой!). Опять же, функция C может быть:
int
call_it (int (*func)(int), int arg)
{
return func (arg);
} Она может использоваться в следующем коде Фортрана:
MODULE m
USE, INTRINSIC :: ISO_C_BINDING
IMPLICIT NONE
! Define interface of C function.
INTERFACE
INTEGER(KIND=C_INT) FUNCTION call_it (func, arg) BIND(C)
USE, INTRINSIC :: ISO_C_BINDING
TYPE(C_FUNPTR), INTENT(IN), VALUE :: func
INTEGER(KIND=C_INT), INTENT(IN), VALUE :: arg
END FUNCTION call_it
END INTERFACE
CONTAINS
! Define procedure passed to C function.
! It must be interoperable!
INTEGER(KIND=C_INT) FUNCTION double_it (arg) BIND(C)
INTEGER(KIND=C_INT), INTENT(IN), VALUE :: arg
double_it = arg + arg
END FUNCTION double_it
! Call C function.
SUBROUTINE foobar ()
TYPE(C_FUNPTR) :: cproc
INTEGER(KIND=C_INT) :: i
! Get C procedure pointer.
cproc = C_FUNLOC (double_it)
! Use it.
DO i = 1_C_INT, 10_C_INT
PRINT *, call_it (cproc, i)
END DO
END SUBROUTINE foobar
END MODULE m
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-4.9.3/gfortran/Working-with-Pointers.html