Передача массива Фортрана через 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 как функция, а не подпрограмма, возможно, стоит рассмотреть.

Другие вопросы по тегам