Zugriff auf (dynamisch zugewiesene) Fortran-Arrays in C

Meine Hauptfrage ist, warum Arrays so seltsame Dinge tun und ob es überhaupt eine Möglichkeit gibt, das Folgende auf "saubere" Weise zu tun.

Ich habe derzeit ein C-Programmfoo.c Anbindung eines Fortran-Programmsbar.f90 überdlopen/dlsym, ungefähr wie im Code unten:

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

Laufende Haupterträge

0.0000000000000000        3.1400000000000001        6.2800000000000002        9.4199999999999999     
0.000000 -nan 0.000000 0.000000 

Dies zeigt, dass Fortran das Array korrekt zuordnet und sogar die angegebenen Werte korrekt speichert, aber nicht mehr über dlsym erreichbar ist (die Bearbeitung dieser Daten führt zu Fehlern). Ich habe dies auch für Arrays mit fester Größe versucht - die Ergebnisse bleiben gleich.

Kennt jemand den Grund für dieses Verhalten? Ich persönlich hätte erwartet, dass die Dinge entweder bidirektional oder gar nicht funktionieren - dieses "Fortran akzeptiert C-Arrays, aber nicht umgekehrt" lässt mich fragen, ob es einen grundlegenden Fehler gibt, den ich beim Zugriff auf das Array von C auf diese Weise gemacht habe.

Die andere (und noch wichtigere) Frage ist, wie man Array-Zugriffe wie diese "auf die richtige Weise" ausführt. Momentan bin ich mir nicht mal sicher, ob das Festhalten an der "Fortran as .so" -Schnittstelle überhaupt ein guter Weg ist - ich denke, es wäre in diesem Fall auch möglich, eine gemischte Programmierung zu versuchen. Trotzdem bleibt das Array-Problem bestehen - ich habe gelesen, dass dies irgendwie mit der ISO C-Bindung gelöst werden könnte, konnte aber noch nicht herausfinden, wie (ich habe noch nicht viel mit Fortran gearbeitet, insbesondere nicht mit der besagten Bindung). , also Hilfe zu diesem Thema wäre sehr dankbar.

Bearbeiten:

Okay, also habe ich in der ISO C-Bindung etwas mehr nachgelesen und einen recht nützlichen Ansatz gefundenHier. VerwendenC_LOC Ich kann C-Zeiger auf meine Fortran-Strukturen bekommen. Leider scheinen Zeiger auf Arrays Zeiger auf Zeiger zu sein und müssen im C-Code dereferenziert werden, bevor sie als C-Arrays behandelt werden können - oder so ähnlich.

Bearbeiten:

Ich habe mein Programm jetzt so eingerichtet, dass es C-Binding verwendet, wie es Vladimir F zumindest größtenteils betont hat. Die C-Datei und Fortran-Dateien sind jetzt miteinander verknüpft, sodass ich die libdl-Schnittstelle zumindest für den Fortran-Teil vermeiden kann. Ich muss noch eine dynamische C-Bibliothek laden, einen Funktionszeiger auf eines der dortigen Symbole abrufen und diesen übergeben als Funktionszeiger auf Fortran, der diese Funktion später als Teil seiner Berechnung aufruft. Da diese Funktion double * s [arrays] erwartet, konnte ich meine Fortran-Arrays seltsamerweise auch nicht mit C_LOC übergebenC_LOC(array) NochC_LOC(array(1)) hat die richtigen Zeiger an die C-Funktion zurückgegeben.array(1) habe den Trick gemacht. Leider ist dies nicht der "sauberste" Weg, dies zu tun. Wenn jemand einen Tipp für mich hat, wie man das mit dem machtC_LOC Funktion, das wäre toll. Trotzdem akzeptiere ich die Antwort von Vladimir F. Ich halte es für die sicherere Lösung.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage