Передача массива Фортрана через ISO_C_BINDING
Я пытаюсь получить базу кода Fortran для вызова библиотеки C с помощью ISO_C_BINDING, но у меня проблемы с передачей массива Fortran.
Я создал простой пример, который иллюстрирует мою проблему.
main.f90
program main
use iso_c_binding
implicit none
interface
subroutine stuff(s,d) bind(c,name='doStuff')
import :: c_char
import :: c_ptr
import :: c_double
character(c_char), value :: s
type(c_ptr), value :: d
end subroutine stuff
end interface
character(len=1) ::c1
real, allocatable :: d1(:)
c1 = 'a'
allocate ( d1(0:10) )
d1(0) = 2.0
d1(1) = 2.5
d1(2) = 3.0
d1(3) = 4.0
write (*,*) d1
call stuff(c1,c_loc(d1))
end program main
func.c
//a function
int doStuff (char c, double* w)
{
printf("%c\n",c);
printf("%d %d %d %d\n",w[0], w[1], w[2], w[3]);
return 1;
}
строка компиляции
icc -c func.c
ifort -o magic.go main.f90 func.o
выход
2.000000 2.500000 3.000000 4.000000 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00 0.0000000E+00
a
0 -1938231792 1 1
Символ передается правильно, а массив - нет, и я не знаю, как его исправить. Примеры, которые я видел, предлагают изменить
double* w
в
void* w
но я не могу этого сделать, так как я не могу изменить код библиотеки, чтобы эта работа работала. Я просто попытался создать новую функцию для void*
в double*
безрезультатно:(. Аналогично, изменение массива так, чтобы оно не могло быть размещено, было бы недопустимо.
Мысли?
1 ответ
У вас проблема с декларацией d1
, Лучше было бы
real(c_double), allocatable, target :: d1(:)
То есть: это должен быть правильный тип, чтобы быть совместимым с двойником C; быть аргументом c_loc
должно быть либо target
или же pointer
приписывать.
Также, как отметил Махонри Морианкумер, ваш printf
формат не подходит для двойника. И, возможно, имея stuff
как функция, а не подпрограмма, возможно, стоит рассмотреть.