Spec-Zone.ru › GNU Fortran 6

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-6.4.0/gfortran/Interoperable-Subroutines-and-Functions.html

Spec-Zone.ru

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