Описание тега fortran-iso-c-binding
Введение
Fortran 2003 предоставляет стандартизированный механизм для взаимодействия с C. Эта поддержка широко доступна в компиляторах Fortran 95, которые частично реализуют Fortran 2003. Эта поддержка охватывает:совместимость процедур - средство ссылки на процедуры, которые определены на языке программирования C или которые могут быть представлены прототипами языка C, а также средство указания того, что процедура, определенная в Fortran, может быть вызвана из C;
совместимость типов - средство объявления типов и перечислений в Фортране, соответствующих типам C;
взаимодействие глобальных объектов данных - средство объявления глобальных переменных, связанных с переменными C с внешней связью;
внутренний модуль (
ISO_C_BINDING
), который обеспечивает доступ к именованным константам и процедурам, относящимся к совместимости C.
Ясно, что любой совместимый объект должен быть таким, чтобы его эквивалентные объявления могли быть сделаны на двух языках. Это обеспечивается в программе Fortran, требуя, чтобы все такие объекты были совместимы. Мы, в свою очередь, объясним, что требуется для типов, переменных и процедур. Закончим двумя примерами.
Взаимодействие внутренних типов
Существует внутренний модуль, называемый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
.Взаимодействие с указателями 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 ofX
.
X
is permitted to be a procedure that is interoperable (see para. 5) or a variable that has theTARGET
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 ifC_PTR1
is aC null pointer
or ifC_PTR2
is present with a different value; otherwise, it has the value true.C_F_POINTER (CPTR, FPTR [, SHAPE])
is a subroutine with argumentsCPTR
is a scalar of typeC_PTR
with intentIN
. Its value is the C address of an entity that is is interoperable with variables of the type and type parameters ofFPTR
. It shall not be the C address of a Fortran variable that does not have theTARGET
attribute.FPTR
это указатель, который становится указателем, связанным с цельюCPTR
. Если это массив, его форма определяется какSHAPE
.
SHAPE
(необязательно) - массив первого ранга целочисленного типа с намерениемIN
. Если есть, то его размер равен рангуFPTR
. ЕслиFPTR
это массив, он должен присутствовать.
Это механизм передачи динамических массивов между языками. Указатель Fortran или массив предполагаемой формы не могут быть переданы в C, поскольку его элементы не обязательно должны быть смежными в памяти. Однако выделенный для размещения массив может быть передан в C, а массив, выделенный в C, может быть связан с указателем Fortran.
Взаимодействие производных типов
Чтобы производный тип мог взаимодействовать, он должен иметь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, orstruct
type that contains a flexible array member.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]
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.
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.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))...
- 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);