Как получить доступ к динамически размещаемым массивам Fortran в C

Мой главный вопрос заключается в том, почему массивы делают такие странные вещи и есть ли вообще какой-либо способ сделать следующее в & quot; чистом & quot; путь.

У меня в настоящее время есть программа Cfoo.c взаимодействие с программой на Фортранеbar.f90 с помощьюdlopen/dlsymпримерно как в коде ниже:

foo.c:

#include <dlfcn.h>
#include <stdio.h>

int main()
{
int i, k = 4;
double arr[k];
char * e;

void * bar = dlopen("Code/Test/bar.so", RTLD_NOW | RTLD_LOCAL);

void (*allocArray)(int*);
*(void **)(&allocArray) = dlsym(bar, "__bar_MOD_allocarray");
void (*fillArray)(double*);
*(void **)(&fillArray) = dlsym(bar, "__bar_MOD_fillarray");
void (*printArray)(void);
*(void **)(&printArray) = dlsym(bar, "__bar_MOD_printarray");
double *a = (double*)dlsym(bar, "__bar_MOD_a");

for(i = 0; i < k; i++)
    arr[i] = i * 3.14;

(*allocArray)(&k);
(*fillArray)(arr);
(*printArray)();
for(i = 0; i < 4; i++)
    printf("%f ", a[i]);
printf("\n");

return 0;
}

bar.f90:

module bar

integer, parameter :: pa = selected_real_kind(15, 307)
real(pa), dimension(:), allocatable :: a
integer :: as

contains

subroutine allocArray(asize)
    integer, intent(in) :: asize

    as = asize
    allocate(a(asize))

    return
end subroutine

subroutine fillArray(values)
    real(pa), dimension(as), intent(in) :: values

    a = values
    return
end subroutine

subroutine printArray()
    write(*,*) a
    return
end subroutine

end module

Запуск основных урожаев

0.0000000000000000        3.1400000000000001        6.2800000000000002        9.4199999999999999     
0.000000 -nan 0.000000 0.000000 

это показывает, что Fortran правильно распределяет массив и даже правильно хранит заданные значения, но они больше не доступны через dlsym (работа с этими данными приводит к ошибкам сегмента). Я также попробовал это для массивов фиксированного размера - результаты остались прежними.

Кто-нибудь знает причину такого поведения? Лично я ожидал, что что-то получится либо двунаправленным, либо, альтернативно, совсем не так - это «Фортран» принимает массивы C, но не наоборот ». меня интересует, не совершил ли я какую-то основную ошибку при доступе к массиву из C таким способом.

Другой (и даже более важный) вопрос состоит в том, как сделать доступ к массиву, подобный этому, «правильным способом». В настоящее время я даже не уверен, что придерживаюсь "Fortran as .so" Интерфейс - это вообще хороший способ - я думаю, что в этом случае также можно попробовать смешанное программирование. Тем не менее, проблема с массивами остается - я читал, что это можно как-то решить, используя привязку ISO C, но я пока не могу понять, как (пока я много не работал с Fortran, особенно, особенно с упомянутой связыванием). , поэтому помощь по этому вопросу будет принята с благодарностью.

Edit:

Итак, я прочитал немного больше об ISO C Binding и нашел довольно полезный подходВот, С помощьюC_LOC Я могу получить C-указатели на мои структуры Fortran. К сожалению, указатели на массивы, кажется, являются указателями на указатели и должны быть разыменованы в коде C, прежде чем их можно будет рассматривать как массивы C - или что-то в этом роде.

Edit:

Теперь моя программа работает, используя привязку C, как указал Владимир F, по крайней мере, по большей части. Файл C и файлы Fortran теперь связаны друг с другом, так что я могу избежать интерфейса libdl, по крайней мере, для части Fortran - мне все еще нужно загрузить динамическую библиотеку C, получить указатель функции на один из символов и передать его как указатель на функцию Fortran, которая позже вызывает эту функцию как часть своего вычисления. Поскольку указанная функция ожидает двойные * s [массивы], мне не удалось передать мои массивы Fortran с помощью C_LOC, как ни странно - ниC_LOC(array) ниC_LOC(array(1)) передал правильные указатели обратно в функцию C.array(1) сделал трюк, хотя. К сожалению, это не "самый чистый" способ сделать это. Если у меня есть подсказка, как это сделать, используяC_LOC функция, это было бы здорово. Тем не менее я принимаю ответ Владимира Ф, так как считаю его более безопасным решением.

Ответы на вопрос(2)

Ваш ответ на вопрос