Linker Fehler 2005 beim mehrfachen includen von Macros



  • Hallo,

    um ein COM Objekt recht einfach zu benutzen habe ich mir ein paar Macros geschrieben. Das funktioniert auch super, wenn das Makro nur in einer cpp Datei benutzt wird.
    Möchte ich aber das Makro in mehreren cpp Dateien benutzen, d.h. ich includier die Header des Makros in die stdafx.h damit das schön überall bekannt ist, dann kommt für jedes include der Linkerfehler 2005.

    Noch ein bisschen Code zum besseren Verstehen:

    ILog * ILOG;
    #define __init_log__()      {   HRESULT hr = CoInitialize(0);\
                                         hr = CoCreateInstance(CLSID_Log, NULL, CLSCTX_INPROC_SERVER, IID_ILog, (void**)&ILOG); }
    

    Log.h

    Damit ich den Zeiger ILOG überall benutzen kann, muss ich ihn ja wohl auch überall includieren. Wie krieg ich dann den Linkerfehler weg?
    Ich könnte die Makros wegschmeissen, dann gehts. Das möcht ich aber nicht unbedingt.

    F1 bringt:
    symbol already defined in object
    The given symbol, displayed in its decorated form, was multiply defined.

    OK OK multiply defined. Aber wie krieg ich das weg!?

    Gruß



  • Das Makro ist nicht das Problem (das bleibt irgendwo auf dem Weg zum Compiler auf der Strecke), aber dein ILog* ILOG; - damit definierst du in jeder Übersetzungseinheit so einen Zeiger und der Linker stolpert dann darüber, daß er ein halbes Dutzend gleichnamige Variablen findet und nicht mehr weiß, wann welche zu verwenden ist. Als Lösungen kann ich dir zwei Varianten anbieten:

    1. static ILog* ILOG;
      Damit beschränkt sich die Sichtbarkeit jedes dieser Zeiger auf "seine" Übersetzungseinheit und der Linker bekommt nichts mehr davon mit. Allerdings bin ich mir nicht sicher, ob das wirklich das ist, was du beabsichtigst (jede ÜE hat ihre eigene Version von ILOG).
    2. extern ILog* ILOG;
      Damit reduzierst du die Definition zu einer reinen Deklaration (mehrfache Deklarationen sind erlaubt) - definieren mußt du die Variable gesondert und in genau einer CPP-Datei (am besten die, wo du die Variable auch initialisieren willst).


  • Ja, wenn ich die Makros weglasse , dann kann ich mit extern ILog* ILOG arbeiten. Aber mit den Makros gibt esProbleme mit den
    CLSID_Log, IID_ILog, ILOG usw, mit allen Variablen eben, di3e im Makro definiert sind.



  • In dem Makro dort oben werden doch gar keine Variablen definiert (außer hr - und das ist lokal, also für den Linker unwichtig). Du hast im ganzen Programm nur eine Version deiner Variablen, also solltest du die an eine Stelle zusammenfassen - und dort auch initialisieren.



  • OK OK noch mal ganz langsam. Ich versteh es bald selbst nicht mehr.

    Mein COM Objekt liefert mir 2 Dateien, die ich includieren muss, darin steht zB:

    EXTERN_C const IID IID_ILog;
    und
    const IID IID_ILog = {0x52E3E759,0xE99D,0x4F50,{0xB7,0x37,0x25,0x9C,0xD6,0x0A,0x1E,0xB9}};
    

    Zusätzlich hab ich noch eine 3.Header mit anderen globalen Sachen. Damit ich keine 3 Header in allen Projekten includieren muss, habe ich eine 4. Header geschrieben mit diesen Makros, die diese Variablen beinhalten:

    #ifndef __log_glob_h_
    #define __log_glob_h_
    
    #include "log.h"
    #include "log_i.c"
    #include "log_types.h"
    
    ILog * ILOG;
    ITrace * ITRACE;
    
    #define __init_log__      {   HRESULT hr = CoInitialize(0);\
                                         hr = CoCreateInstance([b]CLSID_Log[/b], NULL, CLSCTX_INPROC_SERVER, [b]IID_ILog[/b], (void**)&[b]ILOG[/b]);\}
    

    So, überwall, wo ich nun loggen will muss ich ILOG bekanntmachen und daher schreib ich:
    #include "log_glob.h"
    Der Linker meckert dann nämlich nicht nur wegen dem ILOG, sondern auch wegen dem CLSID_Log, wegen dem IID_Log, eben alle Variablen die in diesen mehrfach includierten Headern definiert sind. Und die definiere ich ja nicht mal selber, das macht das COM Objekt selber.

    Wenn ich die Makros jetzt wegschmeisse und die 3 Header nur an einer Stelle includier und an allen anderen Stellen mit der Deklaration extern ILog* ILOG arbeite, dann gehts ja. Ich möchte aber die Makros in irgendeiner Form behalten, damit man zum benutzen des Logs nur 3 Zeilen Kode braucht, nämlich:

    #include "log_glob.h"
    __init_log__;
    ILOG->write(txt);
    

    und an ganz anderer Stelle nur noch 2 Zeilen:

    #include "log_glob.h"
    ILOG->write(txt);
    

    Wie krieg ich den Linker zum Schweigen??

    Gruß und vielen Dank schonmal



  • #include "log_i.c" - das ist übel (lass mich raten, dort steht die Definition der Variablen drin). .C Files werden nicht inkludiert, sondern parallel übersetzt und mitverlinkt.

    (auf deutsch: Nimm diesen Eintrag aus deinem Header heraus und pack die "log_i.c" als eigenständige Quelldatei in dein Projekt rein)


Anmelden zum Antworten