2009-03-19 3 views
1

Grüße Jeder.UNIX Symbol Referenzierungsfehler

Ich versuche derzeit ein mehrsprachiges Programm (C, C++ und FORTRAN) mit GNU-Compiler in UNIX zu kompilieren (g ++, gcc & f77). Alle

meine Quellen kompilieren in Objekte ohne Fehler aber begegne ich ein Symbol Referenzierung Fehler, wie sie verknüpft sind, wie unten dargestellt:

f77 -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -o SlowDynamic.exe main.o \ 
     SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o\ 
     BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o 
NOTICE: Invoking /usr/bin/f90 -f77 -ftrap=%none -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -o SlowDynamic.exe main.o SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o 
Undefined      first referenced 
symbol        in file 
_Znwj        SA.o 
_ZNSt14basic_ofstreamIcSt11char_traitsIcEED1Ev SA.o 
_ZNSt14basic_ofstreamIcSt11char_traitsIcEEC1Ev SA.o 
_ZNKSsixEj       main.o 
_ZNSolsEPFRSoS_E     SA.o 
_ZNSt14basic_ofstreamIcSt11char_traitsIcEE4openEPKcSt13_Ios_Openmode SA.o 
_ZNSolsEd       SA.o 
_ZNSolsEi       SA.o 
__cxa_end_catch      SA.o 
__cxa_begin_catch     SA.o 
_ZdlPv        SA.o 
_ZNSt14basic_ofstreamIcSt11char_traitsIcEE7is_openEv SA.o 
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_c SA.o 
_ZSt4cerr       SA.o 
_ZSt4cout       SA.o 
_ZNSt14basic_ofstreamIcSt11char_traitsIcEE5closeEv SA.o 
_ZNSt8ios_base4InitD1Ev    main.o 
_ZNSt8ios_base4InitC1Ev    main.o 
_ZNKSt9basic_iosIcSt11char_traitsIcEEntEv SA.o 
__gxx_personality_v0    main.o 
_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc SA.o 
__cxa_rethrow      SA.o 
_ZNKSs4sizeEv      main.o 
_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ SA.o 
ld: fatal: Symbol referencing errors. No output written to SlowDynamic.exe 
*** Error code 1 
make: Fatal error: Command failed for target `SlowDynamic.exe' 

mit folgenden Makefile:

products: SlowDynamic.exe 

SlowDynamic.exe: main.o SA.o mersenne.o CFE.o BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o MA_57.o blas.o MA_57_Depend.o Metis.o 
    f77 -L/usr/sfw/lib -R/usr/sfw/lib -lgcc_s -o SlowDynamic.exe main.o \ 
     SA.o mersenne.o CFE.o MA_57.o blas.o MA_57_Depend.o Metis.o\ 
     BCs.o EMatrix.o Numbering.o KMatrix.o Solve.o 

main.o: main.cpp 
    g++ -c -o main.o main.cpp 

SA.o: SA.cpp 
    g++ -c -o SA.o SA.cpp 

mersenne.o: mersenne.cpp 
    g++ -c -o mersenne.o mersenne.cpp 

CFE.o: CFE.c 
    gcc -c -o CFE.o CFE.c 

MA_57.o: MA_57.f 
    f77 -c -o MA_57.o MA_57.f 

blas.o: blas.f 
    f77 -c -o blas.o blas.f 

MA_57_Depend.o: MA_57_Depend.f 
    f77 -c -o MA_57_Depend.o MA_57_Depend.f 

Metis.o: Metis.f 
    f77 -c -o Metis.o Metis.f 

BCs.o: BCs.c 
    gcc -c -o BCs.o BCs.c 

EMatrix.o: EMatrix.c 
    gcc -c -o EMatrix.o EMatrix.c 

Numbering.o: Numbering.c 
    gcc -c -o Numbering.o Numbering.c 

KMatrix.o: KMatrix.c 
    gcc -c -o KMatrix.o KMatrix.c 

Solve.o : Solve.c 
    gcc -c -o Solve.o Solve.c 

clean: 
    rm *.o Main.exe *.gpi 

Ich habe lesen Sie, dass dies in der Regel die Schuld an fehlenden Bibliotheken ist. Ich weiß, dass der FORTRAN-Code C & fein separat kompiliert (entsprechende Bibliotheken enthalten), wie der C++ - Code selbst kompiliert. Dies führt zu der Annahme, dass die Schnittstelle zwischen den beiden Programmen den Fehler verursacht. Unglücklicherweise habe ich wenig oder gar keine Erfahrung damit, dieses Problem zu lösen, und ohne irgendwelche Hinweise vom Linker ist es schwer voranzukommen. Ich füge die notwendigen Teile meines Programms ein, die sich mit der Schnittstelle zwischen den beiden Seiten des Programms befassen.

Zuerst wird der C++ Teil: SA.h, SA.cpp

SA.h:

class SimAnneal { 
    ... 
    std::vector<float> DensityArray; 
    std::vector<float> EnergyArray; 
    public 
    double ObjFunction(); 
    ... 
} 

SA.ccp:

#include <math.h> 
#include <iostream> 
#include <fstream>   
#include <time.h>   
#include <vector> 
#include "SA.h" 
#include "CFE.h" 
#include "randomc.h" //Includes mersenne.cpp 

double SimAnneal::ObjFunction() 
{ 
    CFE(&DensityArray[0], &EnergyArray[0]); 

     // sends pointers of both arrays to CFE.c and modifies EnergyArray as 
     // shown in CFE.c 

    double SumStrainEnergy = 0; 

    for (int i = 0; i < EnergyArray.size(); i++) 
    { 
     SumStrainEnergy += EnergyArray[i]; //Effectively sum of array 
               //engy[] from CFE.c 
    } 

    return SumStrainEnergy; 
} 

zum anderen die C/FORTRAN-Teil: CFE .h, CFE.c

CFE.h:

#ifdef __cplusplus 
extern "C" { 
#endif 

void CFE(float density[], float energy[]); 

#ifdef __cplusplus 
} 
#endif 

CFE.c:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 
#include "BCs.h" 
#include "EMatrix.h" 
#include "Numbering.h" 
#include "KMatrix.h" 
#include "fg_types.h" 
#include "Solve.h" 

void CFE(float density[], float energy[]) 
{ 
    ...stuff... 

    float * dens; 
    dens = density; //pass pointer of array density[0] in SA.cpp to CFE.c 

    ...more stuff.... 

    float * engy; 
    engy = energy; //pass pointer of array energy[0] in SA.cpp to CFE.c 

    ***Modify engy in some respects****  
} 

die ObjFunction in SA.cpp Wesentlichen in main.cpp genannt wird, die Haupt enthält().

Gibt es sichtbare Fehler?

Gibt es eine Möglichkeit, den Linker zu fragen, was verursacht/wo der Fehler in der Verknüpfung auftritt?

Jede Hilfe wird sehr geschätzt.

Vielen Dank.

+++ EDIT: Ausführlich Feedback-+++

birch $ g++ -v Hello.cpp 
Reading specs from /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/specs 
Configured with: /sfw10/builds/build/sfw10-patch/usr/src/cmd/gcc/gcc-3.4.3/configure --prefix=/usr/sfw --with-as=/usr/ccs/bin/as --without-gnu-as --with-ld=/usr/ccs/bin/ld --without-gnu-ld --enable-languages=c,c++ --enable-shared 
Thread model: posix 
gcc version 3.4.3 (csl-sol210-3_4-branch+sol_rpath) 
/usr/sfw/libexec/gcc/sparc-sun-solaris2.10/3.4.3/cc1plus -quiet -v Hello.cpp -quiet -dumpbase Hello.cpp -mcpu=v7 -auxbase Hello -version -o /var/tmp//cc2JwHRb.s 
ignoring nonexistent directory "/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../sparc-sun-solaris2.10/include" 
#include "..." search starts here: 
#include <...> search starts here: 
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/3.4.3 
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/3.4.3/sparc-sun-solaris2.10 
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../include/c++/3.4.3/backward 
/usr/local/include 
/usr/sfw/include 
/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/include 
/usr/include 
End of search list. 
GNU C++ version 3.4.3 (csl-sol210-3_4-branch+sol_rpath) (sparc-sun-solaris2.10) 
     compiled by GNU C version 3.4.3 (csl-sol210-3_4-branch+sol_rpath). 
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 
Hello.cpp:6:2: warning: no newline at end of file 
/usr/ccs/bin/as -V -Qy -s -xarch=v8 -o /var/tmp//ccvAshv7.o /var/tmp//cc2JwHRb.s 
/usr/ccs/bin/as: Sun Compiler Common 10 Patch 09/04/2007 
/usr/sfw/libexec/gcc/sparc-sun-solaris2.10/3.4.3/collect2 -V -R/usr/sfw/lib -Y P,/usr/ccs/lib:/usr/lib -Qy /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crt1.o /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crti.o /usr/ccs/lib/values-Xa.o /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crtbegin.o -L/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3 -L/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../../../sparc-sun-solaris2.10/lib -L/usr/ccs/lib -L/usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/../../.. /var/tmp//ccvAshv7.o -lstdc++ -lm -R/usr/sfw/lib -lgcc_s -lgcc -lc -R/usr/sfw/lib -lgcc_s -lgcc -lc /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crtend.o /usr/sfw/lib/gcc/sparc-sun-solaris2.10/3.4.3/crtn.o 
ld: Software Generation Utilities - Solaris Link Editors: 5.10-1.490 

Antwort

4

Einige dieser undefinierte Symbole beziehen sich eindeutig auf Standard-C++ Klassen (d.h. Ostream).

Sie müssen sicherstellen, dass Sie mindestens die C++ - Bibliothek verknüpft haben (-lstdC++).

debuggen weiter:

  1. Run f77, g ++, etc, im ausführlichen Modus (-v) mit einzelnen Sprachprogrammen und sehen, welche die Compiler-Bibliotheken enthalten automatisch in der Link-Phase für jede Sprache

  2. Verwenden Sie für Symbole, die sich in Ihrem eigenen Code befinden, nm, um sowohl die Deklarationen der nativen Sprache als auch die nicht systemeigenen Aufrufe zu untersuchen, um festzustellen, wie sie nicht übereinstimmen. Es gibt Regeln für Unterstrichpräfixe usw., die üblicherweise angewendet werden.

(Soweit ich mich erinnern kann, aber es ist 15 Jahre her, dass ich C und Fortran verknüpft sind C Symbole intern immer mit einem Unterstrich vorangestellt, aber Fortran Symbole sind nicht).

+0

Schreiben in -lg ++ direkt nach -lgcc_s tut es nicht. Ich versuche, die Datei wie angegeben ausfindig zu machen, indem ich das Hello World-Skript über den Linker im ausführlichen Modus ausführe. Sein angegebener -lgcc und -lc, aber ersterer wird nicht gefunden. Das ausführliche Feedback wurde als Bearbeitung hinzugefügt. – Raugnar

+0

Sie wollen -lstdC++, nicht -lg ++ –

+0

Prost, das hat es getan. Fulled zusammengestellt! – Raugnar

2

Das Hauptproblem besteht darin, dass Sie den Verknüpfungsschritt mit dem F77-Compiler durchführen, der standardmäßig nicht in der C++ - Standardbibliothek verknüpft ist. Wie Alnitak sagte, gib -lg ++ explizit während des Linkens an, um es zu erhalten.

Wenn Sie C++ - Funktionen aus C-Code (oder aus F77-Code) aufrufen, stellen Sie sicher, dass Sie die Prototypen dieser Funktionen in einem externen "C" {} -Block einschließen, damit ihre Symbolnamen im Standardnamen angezeigt werden C-Form, und nicht die verstümmelte C++ - Form (dies schränkt jedoch einige Dinge ein, wie zB Überladen). Weitere Informationen finden Sie unter here.

0

Normalerweise sollten Sie ein Programm, das einen beliebigen C++ - Code enthält, mit dem C++ - Compiler verknüpfen, indem Sie die Fortran- und C-Bibliotheken zur Verbindungslinie hinzufügen. Weiterhin ist der Standardvorschlag, das main() - Programm C++ oder Fortran zu machen, da die Startsequenzen für C++ unterschiedlich sind. Machen Sie den Fortran-Code zu einer Funktion, die Sie von einem minimalen C++ - Haupt aufrufen.

int main(void) // Assuming no argument handling - probably incorrect 
{ 
    return(fortran_main_program()); 
}