7.1.4 Взаимодействующие подпрограммы и функции
Подпрограммы и функции должны иметь атрибут BIND(C) для совместимости с C. Декларация аргументов-заглушек относительно проста. Однако необходимо быть внимательным, так как C по умолчанию использует передачу по значению, в то время как Fortran обычно ведет себя подобно передаче по ссылке. Кроме того, строки и указатели обрабатываются по-разному. Обратите внимание, что в Fortran 2003 и 2008 годах поддерживаются только массивы с явным размером и с размером по умолчанию, но не массивы с изменяемой формой или с отложенной формой (т.е. массивы с выделением памяти или указатели). Однако они разрешены с техническим спецификацией 29113, см. Дополнительная совместимость Fortran с C
Для передачи переменной по значению используйте атрибут VALUE. Таким образом, следующий прототип C
int func(int i, int *j)
соответствует декларации Fortran
integer(c_int) function func(i,j) use iso_c_binding, only: c_int integer(c_int), VALUE :: i integer(c_int) :: j
Обратите внимание, что аргументам-указателям часто необходим атрибут VALUE, см. Работа с указателями.
Строки обрабатываются совершенно по-разному в C и Fortran. В C строка — это NUL-завершающий массив символов, в то время как в Fortran каждая строка имеет связанную с ней длину и, следовательно, не завершается (например, NUL). Например, если нужно использовать следующую функцию C,
#include <stdio.h>
void print_C(char *string) /* equivalent: char string[] */
{
printf("%s\n", string);
}
чтобы вывести “Hello World” из Fortran, можно вызвать ее с помощью
use iso_c_binding, only: C_CHAR, C_NULL_CHAR
interface
subroutine print_c(string) bind(C, name="print_C")
use iso_c_binding, only: c_char
character(kind=c_char) :: string(*)
end subroutine print_c
end interface
call print_c(C_CHAR_"Hello World"//C_NULL_CHAR)
Как показывает пример, необходимо убедиться, что строка NUL завершается. Кроме того, аргумент-заглушка string функции print_C является массивом с длиной единицы и предполагаемым размером; использование character(len=*) не допускается. В приведенном выше примере используется c_char_"Hello World" для обеспечения того, что строковая литерал имеет правильный тип; обычно, вид символов по умолчанию и c_char одинаковы, и, следовательно, "Hello World" эквивалентны. Однако стандарт этого не гарантирует.
Использование строк теперь проиллюстрировано на примере функции библиотеки C strncpy, прототип которой
char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
Функция strncpy копирует не более n символов из строки s2 в s1 и возвращает s1. В следующем примере мы игнорируем возвращаемое значение:
use iso_c_binding
implicit none
character(len=30) :: str,str2
interface
! Ignore the return value of strncpy -> subroutine
! "restrict" is always assumed if we do not pass a pointer
subroutine strncpy(dest, src, n) bind(C)
import
character(kind=c_char), intent(out) :: dest(*)
character(kind=c_char), intent(in) :: src(*)
integer(c_size_t), value, intent(in) :: n
end subroutine strncpy
end interface
str = repeat('X',30) ! Initialize whole string with 'X'
call strncpy(str, c_char_"Hello World"//C_NULL_CHAR, &
len(c_char_"Hello World",kind=c_size_t))
print '(a)', str ! prints: "Hello WorldXXXXXXXXXXXXXXXXXXX"
end
Встроенные процедуры описаны в Встроенных процедурах.
Далее: Работа с указателями, Предыдущее: Взаимодействующие глобальные переменные, Вверх: Взаимодействие с C [Содержание][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-8.4.0/gfortran/Interoperable-Subroutines-and-Functions.html