GCC: undefined reference to [...]



  • Hallo!
    Ich kompiliere in Ubuntu 11.04 gerade ein Projekt, das Funktionen einer statischen Bibliothek aufruft. Die Bibliothek selbst hab ich in C++ geschrieben (mit g++ kompiliert). Die aufrufende Code-Datei ist in C (mit gcc kompiliert) geschrieben und inkludiert eine Header-Datei, welche alle Prototypen der Bibliothek deklariert, allerdings bekomme ich 2x einen "undefined reference to `[Funktionsname]'".

    Hier der Code:

    // Inhalt der Bibliothek (C++)
    #include <taglib/tag.h>
    #include <taglib/fileref.h>
    
    static TagLib::FileRef file;
    
    void readFile (const char *fileName)
    { file = TagLib::FileRef (fileName); }
    
    inline char *itos (int val) // integer-to-string
    {
        static char buf[4] = { 0 };
        int i = 2;
    
        for (; (i && val); i--, val /= 10)
        {
            buf[ i ] = "0123456789"[val%10];
        }
        return &buf[i+1];
    }
    
    const char *getArtist (void) { return (file.isNull()) ? NULL : file.tag()->artist().toCString(); }
    const char *getTitle (void) { return (file.isNull()) ? NULL : file.tag()->title().toCString(); }
    const char *getAlbum (void) { return (file.isNull()) ? NULL : file.tag()->album().toCString(); }
    const char *getGenre (void) { return (file.isNull()) ? NULL : file.tag()->genre().toCString(); }
    const char *getYear (void) { return (file.isNull()) ? NULL : itos(file.tag()->year()); }
    const char *getTrack (void) { return (file.isNull()) ? NULL : itos(file.tag()->track());}
    

    Nach dem Kompilieren wird die .a-Datei zu "libtag_static.a" umbenannt und in /usr/lib verschoben.

    // Inhalt der libtag_static.h (C90)
    #ifndef LIBTAG_STATIC_H
    #define LIBTAG_STATIC_H
      extern void readFile (const char *fileName);
      extern const char *getArtist (void);
      extern const char *getTitle (void);
      extern const char *getAlbum (void);
      extern const char *getGenre (void);
      extern const char *getYear (void);
      extern const char *getTrack (void);
    #endif
    
    // Inhalt der aufrufenden Datei (C90)
    #include "libtag_static.h"
    //[...]
    readFile (src); // undefined reference to `readFile'
    // Anm.: strrep wurde in einer anderen Datei ausprogrammiert, funktioniert einwandfrei und hat hiermit eigentlich nichts zu tun.
    strcpy (sDstName, strrep(sDstName, "?Artist", getArtist())); // undefined reference to `getArtist'
    

    Die .a-Datei hab ich im Fenster "Build Options" > "Linker settings" schon bei "Link libraries" hinzugefügt... mir fällt einfach nicht ein, was ich sonst falsch gemacht haben könnte.

    Danke im Voraus, aVoX.



  • Dir fehlt das extern "C" fürs Name-Mangling

    extern "C" {
    
    void readFile (const char *fileName)
    { file = TagLib::FileRef (fileName); }
    
    const char *getArtist (void) { return (file.isNull()) ? NULL : file.tag()->artist().toCString(); }
    const char *getTitle (void) { return (file.isNull()) ? NULL : file.tag()->title().toCString(); }
    const char *getAlbum (void) { return (file.isNull()) ? NULL : file.tag()->album().toCString(); }
    const char *getGenre (void) { return (file.isNull()) ? NULL : file.tag()->genre().toCString(); }
    const char *getYear (void) { return (file.isNull()) ? NULL : itos(file.tag()->year()); }
    const char *getTrack (void) { return (file.isNull()) ? NULL : itos(file.tag()->track());}
    }
    
    // Inhalt der libtag_static.h (C90)
    #ifndef LIBTAG_STATIC_H
    #define LIBTAG_STATIC_H
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
      void readFile (const char *fileName);
      const char *getArtist (void);
      const char *getTitle (void);
      const char *getAlbum (void);
      const char *getGenre (void);
      const char *getYear (void);
      const char *getTrack (void);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif
    

    http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html



  • Ok, ich hab' mich jetzt ein wenig schlau gemacht (danke für den Link 🙂 ) und die beiden Dateien umgebessert... aber es funktioniert immernoch nicht 😞



  • Wie schaut der genaue Compiler/Linker-Aufruf aus?



  • Dieser Thread wurde von Moderator/in rüdiger aus dem Forum C (C89 und C99) in das Forum Compiler- und IDE-Forum verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • rüdiger schrieb:

    Wie schaut der genaue Compiler/Linker-Aufruf aus?

    Ich führe Compiler und Linker nicht händisch aus, sondern über die IDE.
    PS: Danke fürs Verschieben.



  • aVoX schrieb:

    rüdiger schrieb:

    Wie schaut der genaue Compiler/Linker-Aufruf aus?

    Ich führe Compiler und Linker nicht händisch aus, sondern über die IDE.
    PS: Danke fürs Verschieben.

    Wie du es aufrufst ist ja egal. Aber offenbar scheitert dort etwas. Ansonsten kannst du mit man: nm auch nachschauen, welche Symbole exportiert werden.



  • Danke für den Tipp mit "nm".
    Aber es scheint alles in bester Ordnung zu sein:

    $ nm -e libtag_static.a
    main.o:
    00000325 t _GLOBAL__I_readFile
             U _Unwind_Resume
    00000004 b _ZL4file
             U _ZN6TagLib6StringD1Ev
             U _ZN6TagLib7FileRefC1EPKcbNS_15AudioProperties9ReadStyleE
             U _ZN6TagLib7FileRefC1Ev
             U _ZN6TagLib7FileRefD1Ev
             U _ZN6TagLib7FileRefaSERKS0_
             U _ZNK6TagLib6String9toCStringEb
             U _ZNK6TagLib7FileRef3tagEv
             U _ZNK6TagLib7FileRef6isNullEv
             U _ZNSt8ios_base4InitC1Ev
             U _ZNSt8ios_base4InitD1Ev
    00000000 b _ZStL8__ioinit
    00000000 u _ZZ4itosiE3buf
             U __cxa_atexit
             U __dso_handle
             U __gxx_personality_v0
    00000149 T getAlbum
    0000005f T getArtist
    000001be T getGenre
    000000d4 T getTitle
    000002ac T getTrack
    00000233 T getYear
    00000000 T readFile
    

    T steht für ein globales Symbol im Text-Segment, also müsste das eigentlich richtig sein. 😕


Anmelden zum Antworten