Spec-Zone.ru › GNU Fortran 8

7.1.5 Работа с указателями

Указатели C в Fortran представлены специальным неявным производным типом type(c_ptr) (с закрытыми компонентами). Поэтому необходимо использовать внутренние процедуры преобразования для преобразования из указателей C или в них.

Для некоторых приложений использование типа с предполагаемым типом (TYPE(*)) может быть альтернативой указателю C; см. Дополнительная взаимосвязь Fortran с 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 в Fortran необходимо передать одномерный SHAPE аргумент.

Если указатель является аргументом-псевдопеременной интерактивной процедуры, то, как правило, он должен быть объявлен с использованием атрибута VALUE . void* соответствует TYPE(C_PTR), VALUE, а TYPE(C_PTR) в одиночку соответствует void**.

Указатели процедур обрабатываются аналогично указателям; тип C — TYPE(C_FUNPTR), а внутренние процедуры преобразования — C_F_PROCPOINTER и C_FUNLOC.

Рассмотрим два примера передачи указателя процедуры из C в Fortran и наоборот. Обратите внимание, что эти примеры также очень похожи на передачу обычных указателей между этими двумя языками. Сначала рассмотрим этот код на 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 в Fortran, которая правильно получает указатель процедуры из 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, которая ожидает аргумент указателя процедуры и передать ей процедуру Fortran (которая, очевидно, должна быть совместима!). Опять же, функция C может быть:

int
call_it (int (*func)(int), int arg)
{
  return func (arg);
}

Её можно использовать в следующем коде Fortran:

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

Далее: Дополнительная взаимосвязь Fortran с C, Предыдущее: Совместимые подпрограммы и функции, Вверх: Взаимодействие с C [Оглавление][Индекс]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-8.4.0/gfortran/Working-with-Pointers.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API