Описание тега fortran-iso-c-binding

Стандартная совместимость Fortran с C состоит из атрибута `BIND(C)`, который включает соглашения о вызовах C и изменяет имена символов, и модуля ISO_C_BINDING, который обеспечивает доступ к именованным константам, которые представляют параметры типа вида представлений данных, совместимых с типами C, производный тип C_PTR, соответствующий любому типу указателя данных C, производный тип C_FUNPTR, соответствующий любому типу указателя функции C, и четыре процедуры.
  1. Введение
    Fortran 2003 предоставляет стандартизированный механизм для взаимодействия с C. Эта поддержка широко доступна в компиляторах Fortran 95, которые частично реализуют Fortran 2003. Эта поддержка охватывает:

    • совместимость процедур - средство ссылки на процедуры, которые определены на языке программирования C или которые могут быть представлены прототипами языка C, а также средство указания того, что процедура, определенная в Fortran, может быть вызвана из C;

    • совместимость типов - средство объявления типов и перечислений в Фортране, соответствующих типам C;

    • взаимодействие глобальных объектов данных - средство объявления глобальных переменных, связанных с переменными C с внешней связью;

    • внутренний модуль (ISO_C_BINDING), который обеспечивает доступ к именованным константам и процедурам, относящимся к совместимости C.

Ясно, что любой совместимый объект должен быть таким, чтобы его эквивалентные объявления могли быть сделаны на двух языках. Это обеспечивается в программе Fortran, требуя, чтобы все такие объекты были совместимы. Мы, в свою очередь, объясним, что требуется для типов, переменных и процедур. Закончим двумя примерами.

  1. Взаимодействие внутренних типов
    Существует внутренний модуль, называемыйISO_C_BINDINGкоторый содержит именованные константы, содержащие значения параметров типа kind для внутренних типов. Их имена показаны в таблице 1 вместе с соответствующими типами C. Не требуется, чтобы процессор поддерживал их все. Отсутствие поддержки обозначается отрицательным значением.

    Таблица 1. Взаимодействие между Fortran и типами C

    Тип Именованная константа Тип или типы C
    INTEGER     C_INT                 int, подписанное int
                C_SHORT короткое int, подписанное короткое int
                C_LONG длинный int, подписанный длинный int
                C_LONG_LONG длинный длинный int, длинный длинный int со знаком
                C_SIGNED_CHAR знаковый символ, беззнаковый символ
                C_SIZE_T size_t
                C_INT_LEAST8_T int_least8_t
                C_INT_LEAST16_T int_least16_t
                C_INT_LEAST32_T int_least32_t
                C_INT_LEAST64_T int_least64_t
                C_INT_FAST8_T int_fast8_t
                C_INT_FAST16_T int_fast16_t
                C_INT_FAST32_T int_fast32_t
                C_INT_FAST64_T int_fast64_t
                C_INTMAX_T c intmax_t
    REAL C_FLOAT float, float _Imaginary
                C_DOUBLE двойной, двойной _Imaginary
    COMPLEX C_LONG_DOUBLE длинный двойной, длинный двойной _Imaginary
                C_COMPLEX _Complex
                C_DOUBLE_COMPLEX двойной _комплекс
                C_LONG_DOUBLE_COMPLEX длинный двойной _комплекс
    ЛОГИЧЕСКИЙ C_BOOL _Bool
    CHARACTER C_CHAR char  
    

    Для символа совместимость также требует, чтобы параметр типа длины был опущен или задавался выражением инициализации, значение которого равно единице. Предоставляются следующие именованные константы (с очевидным значением):C_NULL_CHAR, C_ALERT, C_BACKSPACE, C_FORM_FEED, C_NEW_LINE, C_CARRIAGE_RETURN, C_HORIZONTAL_TAB, C_VERTICAL_TAB.

  2. Взаимодействие с указателями C
    Для взаимодействия с указателями C (которые являются просто адресами) модуль содержит производный типC_PTR который совместим с любым типом указателя C и именованной константой C_NULL_PTR со значением NULL of C.
    The module also contains the following procedures:

    • C_LOC (X) is an inquiry function that returns the C address of X.
      X is permitted to be a procedure that is interoperable (see para. 5) or a variable that has the TARGET attribute and is either interoperable or is an allocated allocatable variable that has interoperable type and type parameters.
    • C_ASSOCIATED (C_PTR1[, C_PTR2]) is an inquiry function that returns a default logical scalar. It has the value false if C_PTR1 is a C null pointer or if C_PTR2 is present with a different value; otherwise, it has the value true.
    • C_F_POINTER (CPTR, FPTR [, SHAPE]) is a subroutine with arguments CPTR is a scalar of type C_PTR with intent IN. Its value is the C address of an entity that is is interoperable with variables of the type and type parameters of FPTR. It shall not be the C address of a Fortran variable that does not have the TARGET attribute. FPTR это указатель, который становится указателем, связанным с целью CPTR. Если это массив, его форма определяется какSHAPE.
      SHAPE (необязательно) - массив первого ранга целочисленного типа с намерением IN. Если есть, то его размер равен рангуFPTR. ЕслиFPTR это массив, он должен присутствовать.

    Это механизм передачи динамических массивов между языками. Указатель Fortran или массив предполагаемой формы не могут быть переданы в C, поскольку его элементы не обязательно должны быть смежными в памяти. Однако выделенный для размещения массив может быть передан в C, а массив, выделенный в C, может быть связан с указателем Fortran.

  3. Взаимодействие производных типов
    Чтобы производный тип мог взаимодействовать, он должен иметьBIND атрибут явно:

    ТИП, СВЯЗКА (C):: MYTYPE:
    КОНЕЦ ТИП MYTYPE
    

    Each component must have interoperable type and type parameters, must not be a pointer, and must not be allocatable. This allows Fortran and C types to correspond, for example:

    typedef struct {
        int m, n;
        float r;
    } myctype
    

    is interoperable with

    USE ISO_C_BINDING
    TYPE, BIND(C):: MYFTYPE
        INTEGER(C_INT):: I, J
        REAL(C_FLOAT):: S
    END TYPE MYFTYPE
    

    The name of the type and the names of the components are not significant for interoperability.

    No Fortran type is interoperable with a C union type, struct type that contains a bit field, or struct type that contains a flexible array member.

  4. Interoperability of variables
    A scalar Fortran variable is interoperable if it is of interoperable type and type parameters, and is neither a pointer nor allocatable.

    An array Fortran variable is interoperable if it is of interoperable type and type parameters, and is of explicit shape or assumed size. It interoperates with a C array of the same type types parameters and shape, but with reversal of subscripts. For example, a Fortran array declared as:

    INTEGER:: A(18, 3:7, *)
    

    is interoperable with a C array declared as

    int b[][5][18]  
    
  5. Interoperability of procedures A Fortran procedure is interoperable if it has an explicit interface and is declared with the BIND attribute:

    FUNCTION FUNC(I, J, K, L, M) BIND(C)
    

    All the dummy arguments must be interoperable. For a function, the result must be scalar and interoperable. The procedure has a 'binding label', which has global scope and is the name by which it is known to the C processor. By default, it is the lower-case version of the Fortran name. For example, the above function has the binding label func. Another binding label may be specied:

    FUNCTION FUNC(I, J, K, L, M) BIND(C, NAME='C_Func')
    

    Such a procedure corresponds to a C function prototype with the same binding label. For a function, the result must be interoperable. For a subroutine, the prototype must have a void result.

  6. Interoperability of global data An interoperable module variable or a common block with interoperable members may be given the BIND attribute:

    USE ISO_C_BINDING
        INTEGER(C_INT), BIND(C):: C_EXTERN
        INTEGER(C_LONG):: C2
        BIND(C, NAME='myVariable'):: C2
        COMMON /COM/ R, S
        REAL(C_FLOAT):: R, S
        BIND(C):: /COM/
    

    It has a binding label defined by the same rules as for procedures and interoperate with a C variable of a corresponding struct type.

  7. Example of Fortran calling C C Function Prototype:

    int C_Library_Function(void* sendbuf, int sendcount, int *recvcounts)
    

    Fortran Module:

    MODULE FTN_C
        INTERFACE
            INTEGER (C_INT) FUNCTION C_LIBRARY_FUNCTION  &
                (SENDBUF, SENDCOUNT, RECVCOUNTS)         &
                BIND(C, NAME='C_Library_Function')
                USE ISO_C_BINDING
                IMPLICIT NONE
                TYPE (C_PTR), VALUE:: SENDBUF
                INTEGER (C_INT), VALUE:: SENDCOUNT
                TYPE (C_PTR), VALUE:: RECVCOUNTS
            END FUNCTION C_LIBRARY_FUNCTION
        END INTERFACE
    END MODULE FTN_C
    

    Fortran Calling Sequence:

    USE ISO_C_BINDING, ONLY: C_INT, C_FLOAT, C_LOC
    USE FTN_C...
    REAL (C_FLOAT), TARGET:: SEND(100)
    INTEGER (C_INT):: SENDCOUNT
    INTEGER (C_INT), ALLOCATABLE, TARGET:: RECVCOUNTS(:)...
    ALLOCATE(RECVCOUNTS(100))...
    CALL C_LIBRARY_FUNCTION(C_LOC(SEND), SENDCOUNT,     &
    C_LOC(RECVCOUNTS))...
    
  8. Example of C calling Fortran
    Fortran Code:
    SUBROUTINE SIMULATION(ALPHA, BETA, GAMMA, DELTA, ARRAYS) BIND(C)
        USE ISO_C_BINDING
        IMPLICIT NONE
        INTEGER (C_LONG), VALUE:: ALPHA
        REAL (C_DOUBLE), INTENT(INOUT):: BETA
        INTEGER (C_LONG), INTENT(OUT):: GAMMA
        REAL (C_DOUBLE),DIMENSION(*),INTENT(IN):: DELTA
        TYPE, BIND(C):: PASS
            INTEGER (C_INT):: LENC, LENF
            TYPE (C_PTR):: C, F
        END TYPE PASS
        TYPE (PASS), INTENT(INOUT):: ARRAYS
        REAL (C_FLOAT), ALLOCATABLE, TARGET, SAVE:: ETA(:)
        REAL (C_FLOAT), POINTER:: C_ARRAY(:)...! Associate C_ARRAY with an array allocated in C
        CALL C_F_POINTER (ARRAYS%C, C_ARRAY, (/ARRAYS%LENC/))...! Allocate an array and make it available in C
        ARRAYS%LENF = 100
        ALLOCATE (ETA(ARRAYS%LENF))
        ARRAYS%F = C_LOC(ETA)...
    END SUBROUTINE SIMULATION
    
    C Struct Declaration:
    struct pass {int lenc, lenf; float* f, *c}
    
    C Function Prototype:
    void simulation(long alpha, double *beta, long *gamma, double delta[], 
                    struct pass *arrays)
    
    C Calling Sequence:
    simulation(alpha, &beta, &gamma, delta, &arrays);