Re: [maillist] fortran & c

J. Linnenkohl (jlinnen@c-s-k.de)
Sat, 12 Jun 1999 01:43:07 +0200

Jürgen Gumpinger wrote:
>
> Hallo!
> Ich habe für alle fortran routinen den aufruf mit dem _ versehen. Wie
> geht das aber, wenn ich aus einem fortran-file eine routine aus dem
> cpp-file aufrufen will? Ich komm da mit den _ durcheinander. Bis jetzt
> habe ich es so genmacht:
> CPP_FILE:
> extern "C" void error_to_tcl_ (
> int& errNr, int& analysisStopped
> );
> #ifdef WIN32
> #define ERROR_TO_TCL
> void error_to_tcl_ (int& errNr, int& analysisStopped)
> #endif
> #ifdef sgi
> #define ERROR_TO_TCL
> void error_to_tcl_ (int& errNr, int& analysisStopped)
> #endif
> #ifndef ERROR_TO_TCL
>
> void error_to_tcl_(int& errNr, int& analysisStopped)
> #endif
> {
> currentFemfatData->error_to_tcl(errNr, analysisStopped);
> }
> void FemfatData::error_to_tcl (int& errNr, int& analysisStopped) {
> //printf("calling error_to_tcl in c++: errNr= %d\n",errNr);
> }
>
> Und in einem FORTRAN FILE::
> call error_to_tcl(IERROR,IASTOP)
>
> Beim Linken bekomme ich den Fehler:
>
> fortran/felibf.a(gulmud.o): In function `gulmud_':
> gulmud.o(.text+0x254): undefined reference to `error_to_tcl__'
>
> Und zweitens: Ich habe in meinem cpp file immer so ifdef sgi ifdef
> pc,... Gibt es das auch für Linux: ifdef linux???
>
> Danke
>
> Jürgen

Hi,

schade um die Mühe, aber Du kannst getrost wieder die
Routinen error_to_tcl() nennen.

Wenn der Linker ein Symbol (Routine, Funktion, globale Variable)
nicht findet, gibt er Dir den Namen des nicht gefundenen Symbols
immer mit einem _ aus.

Wenn Du ein Modul hast, daß in C++ geschrieben hast um mit einem
C++ Compiler übersetzt ist, wirst Du es schwierig haben, das in
Fortran zu nutzen, weil :
C++ ist objektorient, d.h. alle Routinen sind Methoden eines
Objektes. Um sie von außerhalb des Objektes zu nutzen, müssen
sie auch außerhalb zugreifbar, sprich "public" sein.
In diesem Zusammenhang verstehe ich die extern-Deklaration eh nicht,
diese wird benutzt, um eine Routine oder Variable vom Typ
zu deklarieren, aber dem Compiler mitzuteilen, daß der
Code in einem anderen Module liegt.
Noch eine Sache: in Fortran gibt es nur Call-By-Reference,
du kannst von Fortran nur C-Routinen anspringen, deren
Formalparameter vom Pointer-Type sind.

Zu zweitens. Kommt drauf an, naemlich auf den
Macher des Programms. Kurz ein Beispiel : es gibt unter
UNIX die Datei signal.h. Nun gibt es ein UNIX A (nennen wir es HP-UX),
so liegt signal.h im Ordner /usr/include/sys, inter UNIX B (nennen
wir es AIX) liegt es in /usr/include. (Preisfrage : wo liegt es unter
Linux ?)
Wenn der Programm-Macher sein Programm unter UNIX A und B laufen
lassen will und er signal.h braucht, muß er die beiden Unterschiede
berücksichtigen, indem er schreibt :

#ifdef HP-UX
#include <sys/signal.h>
#elif AIX
#include <signal.h>
#elif .....

Das HP-UX oder AIX definiert sind, muß er im Makefile beim
Compileraufruf setzen, z.B.

os_name = $(shell uname -s)
gcc -D os_name ....

Kompiliert es unter HP-UX, so ist HP-UX gesetzt, unter AIX dann AIX,
unter Linux dann Linux, ....
(Natürlich kann man auch Platform-individuelle Makefiles erstellen
und explizit cc -D sgi dort angeben).

In Deinem Fall oben :

Erst wird die Routine für WIN32 deklariert, dann für sgi. Sind beide
Flags im Makefile nicht gesetzt, trifft die #ifndef ERROR_TO_TCL
Auswahl zu und deklariert die Routine.

Gruß

___________________________________________________
Jörg Linnenkohl
e-mail: jlinnen@c-s-k.de
phone : +49 069 913073 25
fax : +49 069 913073 31
CSK Germany * Meisengasse 13-15 * D-60313 Frankfurt