Cómo acceder a las matrices de Fortran (asignadas dinámicamente) en C

Mi pregunta principal es por qué los arreglos hacen cosas tan extrañas y si hay alguna forma de hacer lo siguiente de manera "limpia".

Actualmente tengo un programa de Cfoo.c interconectando un programa de Fortranbar.f90 víadlopen/dlsym, aproximadamente como en el siguiente código:

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

Ejecución de los principales rendimientos.

0.0000000000000000        3.1400000000000001        6.2800000000000002        9.4199999999999999     
0.000000 -nan 0.000000 0.000000 

lo que muestra que Fortran asigna la matriz correctamente e incluso almacena correctamente los valores dados, pero ya no se puede acceder a ellos a través de dlsym (trabajar en esos datos da como resultado segfaults). También probé esto para arreglos de tamaño fijo: los resultados siguen siendo los mismos.

¿Alguien sabe la razón de este comportamiento? Personalmente, hubiera esperado que las cosas funcionaran de forma bidireccional o, en su defecto, no en absoluto. Este "Fortran acepta matrices C, pero no al revés" me hace preguntarme si hay algún error básico que cometí al acceder a la matriz desde C de esta manera.

La otra pregunta (y aún más importante) es cómo hacer los accesos a la matriz como estos "de la manera correcta". Actualmente, ni siquiera estoy seguro de si seguir la interfaz "Fortran as .so" es una buena forma. Creo que también sería posible intentar una programación mixta en este caso. No obstante, el problema de las matrices sigue siendo: he leído que esto podría resolverse de alguna manera utilizando el enlace ISO C, pero no pude averiguar cómo (aún no he trabajado mucho con Fortran, especialmente, pero no con el enlace mencionado) , por lo que la ayuda en este tema sería muy apreciada.

Editar:

De acuerdo, leí un poco más el enlace ISO C y encontré un enfoque bastante útil.aquí. UtilizandoC_LOC Puedo obtener punteros C en mis estructuras Fortran. Desafortunadamente, los punteros a las matrices parecen ser punteros a los punteros y necesitan ser referenciados en el código C antes de que puedan ser tratados como matrices C, o algo así.

Editar:

Conseguí que mi programa funcionara ahora usando la unión de C de la manera que Vladimir F señaló, al menos en su mayor parte. El archivo C y los archivos Fortran ahora están vinculados entre sí, por lo que puedo evitar la interfaz libdl, al menos para la parte Fortran. Todavía necesito cargar una biblioteca dinámica C, obtener un puntero de función a uno de los símbolos allí y pasar esa como un puntero a la función de Fortran, que luego llama a esa función como parte de su cálculo. Como dicha función espera el doble * s [arreglos], no pude pasar mis arreglos Fortran usando C_LOC, por extraño que parezcaC_LOC(array) niC_LOC(array(1)) Pasó los punteros correctos de nuevo a la función C.array(1) hizo el truco sin embargo Lamentablemente, esta no es la forma "más limpia" de hacer esto. Si alguien me dio una pista sobre cómo hacer esto usando elC_LOC Función, eso sería genial. No obstante, acepto la respuesta de Vladimir F, ya que considero que es la solución más segura.

Respuestas a la pregunta(2)

Su respuesta a la pregunta