======================== C und Fortran Funktionen [TOC] ======================== Wir beginnen mit - einem Fortran Hauptprogramm und - einer Fortran Subroutine Das Fortran Hauptprogramm ruft die Subroutine auf und gibt ein davon abhängiges Ergebnis aus. Dann ersetzen die Fortran Routine mit einer C Funktion. Das Fortran Programm wird das gar nicht merken. Reines Fortran Beispiel ======================= Hauptprogramm ------------- :import: day05/sumtest.f Subroutine ---------- :import: day05/dsum.f Übersetzen, Linken und ausführen -------------------------------- Wir übersetzten die Fortran Source Dateien einzeln und erzeugen zunächst nur Object Files. Bei diesen kann man dann auch mit `otool` prüfen, wo genau Variablen angelegt wurden. *--[SHELL(path=day05)]----------------------------------------------------* | | | gfortran -Wall -fimplicit-none -c dsum.f | | gfortran -Wall -fimplicit-none -c sumtest.f | | | *-------------------------------------------------------------------------* Dann Linken wir diese zu einer ausführbaren Datei (hier werden heimlich noch System Bibliotheken zu den Object Files dazugelinkt): *--[SHELL(path=day05)]----------------------------------------------------* | | | gfortran dsum.o sumtest.o | | | *-------------------------------------------------------------------------* Jetzt kann man testen was das Ganze tut: *--[SHELL(path=day05)]----------------------------------------------------* | | | ./a.out | | | *-------------------------------------------------------------------------* *Aufgabe:* - Findet mit `otool` heraus, wie die Funktion auf Assembler Ebene heisst. - Wie werden die Argumente übergeben? Call by value oder call by reference? - In der Praxis schaut man das schnell mit `nm` nach. Lest nach was `nm` tut und probiert es aus! Fortran Funktion mit C-Funktion ersetzen ======================================== Mit folgender C-Funktion kann man die Fortran Routine ersetzen: :import: day05/new_dsum.c Wir erzeugen für die C-Funktion das Object File *--[SHELL(path=day05)]----------------------------------------------------* | | | gcc-4.8 -Wall -c new_dsum.c | | | *-------------------------------------------------------------------------* Und linken mit dem Object File des Hauptporgramms *--[SHELL(path=day05)]----------------------------------------------------* | | | gfortran new_dsum.o sumtest.o | | | *-------------------------------------------------------------------------* Jetzt kann man wieder testen ob das Ganze tut: *--[SHELL(path=day05)]----------------------------------------------------* | | | ./a.out | | | *-------------------------------------------------------------------------* Makefile ======== Schaut euch folgendes (viel zu primitives) Makefile an: - Mit `make sum_f77` soll die reine Fortran Variante übersetzt und gelinkt werden. Die ausführbare Datei soll `sum_f77` heissen. - Mit `make sum_c` soll die gemischte Fortran/C Variante übersetzt und gelinkt werden. Die ausführbare Datei soll `sum_c` heissen. - Mit `make` sollen beide Varianten erzeugt werden. - Mit `make clean` sollen alle Object Files und ausführbaren Dateien gelöscht werden. - Wenn ein Object File bereits existiert, dann soll es nur neu erzeugt werden, wenn sich das zugehörige Source File geändert hat. - Eine ausführbare Datei muss nur neu erzeugt (bzw. neu gelinkt) werden, wenn sich ein Object File geändert hat. :import: day05/Makefile *Aufgabe*: Verbessert es - Prüft, ob das Makefile tut was es soll! - Zweimal hintereinander `make` aufrufen. - Zeitstempel eines Source Files ändern und nochmals `make` aufrufen - Object File löschen und nochmals `make` aufrufen. - ... - Variablen für C-Compiler und Fortran-Compiler - Variablen für C bzw. Fortran Source Files ... - Variablen für Compiler Flags, Linker, ... - Regeln für das Erzeugen von Object Files. - Wieso `rm -f` und nicht nur `rm`? :navigate: __up__ -> doc:index __next__ -> doc:day05/page02