lnk2005 bei vorkompilierten headern



  • hallo zusammen,

    ich bin gerade auf visual studio 2012 umgestiegen und kann dort nicht mehr mit vorkompilierten headern (vh) arbeiten. in 2010 funktionierte noch alles tadellos, seitdem habe ich nichts am quellcode verändert. eine dll kompiliert fehlerfrei ohne vh, mit bekomme ich einige dieser fehler:

    error LNK2005: "enum libdf::TDefectCode __cdecl libdf::defectCodeFromDFormat(unsigned char)" (?defectCodeFromDFormat@libdf@@YA?AW4TDefectCode@1@E@Z) ist bereits in defectcodes.obj definiert.
    

    in der defectcodes.h steht:

    #ifndef __DEFECTCODES_H__
    #define __DEFECTCODES_H__
    
    namespace libdf {
    
    typedef enum {
    	DC_I1 = 100, //!< 10% innen
    	DC_I2,       //!< 20% innen
    	DC_I3,       //!< 30% innen
    	DC_NONE      //!< kein Code vergeben, sozusagen nicht initialisiert
    } TDefectCode;
    
    /** liefert zu einem DefectCode einen String, der den lesbaren
     * Code enthält.
     * @param defectCode zu konvertierender Code
     * @return lesbarer Code
     */
    __declspec(dllexport) wxString defectCodeToString(TDefectCode defectCode);
    
    }
    
    #endif
    

    und in der defectcodes.cpp

    #include "defectcodes.h"
    
    __declspec(dllexport) wxString libdf::defectCodeToString( TDefectCode defectCode )
    {
    	int dep;
    	char classes[] = "-" "O" "P" "X" "S" "B" "D" "N" 
    		"R" "T" "W" "Z" "V" "!" "?";
    
    	switch(defectCode) {
    	case DC_I1:
    	case DC_I2:
    	case DC_I3:
    		dep = (int) defectCode - 100 + 1;
    		if(dep == 10) dep = 0;
    		return wxString::Format(_("%dI"), dep);
    	case DC_NONE: //kein Code vergeben, sozusagen nicht initialisiert
    		return wxString::Format(_T("%c"), classes[(int) defectCode - 300]);
    	}
    	return wxEmptyString;
    }
    

    wie kann ich den lnk2005 beheben?
    danke!



  • Das ist kein C++ Problem.

    Es wird die Funktion defectCodeFromDFormat bemängelt, die kommt in deinen Codeschnipseln nicht vor.



  • hab den quellcode auf das wesentliche reduziert, die fehlermeldung lautet dem code entsprechend

    error LNK2005: "class wxString __cdecl libdf::defectCodeToString(enum libdf::TDefectCode)" (?defectCodeToString@libdf@@YA?AVwxString@@W4TDefectCode@1@@Z) ist bereits in defectcodes.obj definiert.

    wenn es kein c++ problem ist, dann eins von visual studio?



  • mael15 schrieb:

    wenn es kein c++ problem ist, dann eins von visual studio?

    Da es laut deiner Aussage ohne pch fehlerfrei funktioniert, ja!



  • Was micht hier etwas wundert ist der Inhalt der Header-Datei. Wenn das eine Schnittstelle für eine DLL sein soll, hätte ich so etwas wie das hier erwartet:

    #ifndef LIBDF_H_INCLUDED
    #define LIBDF_H_INCLUDED
    
    #include <string>
    
    #ifdef BUILD_LIBDF
      #define LIBDFDECL __declspec(dllexport)
    #else
      #define LIBDFDECL __declspec(dllimport)
    #endif
    
    LIBDFDECL std::string defectCodeToString(int code);
    
    #endif
    

    Denn beim Erzeugen der DLL ist es wichtig, die Funktionen zu markieren, die man nach außen Hin sichtbar haben will (dllexport) und beim Verwenden einer solchen Funktion ist es wichtig, zu sagen, dass es sich um eine Funktion handelt, die in irgendeiner DLL steckt (dllimport). Soweit reicht zumindest mein Windows/DLL Verständnis.

    Und wenn man diesen Header vorkompiliert, könnte das schon Probleme machen, weil ja einmal BUILD_LIBDF definiert und einmal nicht definiert sein würde. Aber ich muss gestehen, dass ich dieses PCH-Zeug nicht durchblicke, es nie verwende und immer mit einem komplett leeren Projekt anfange.



  • jup, dieses konstrukt verwende ich auch. da der fehler derselbe ist wenn ich direkt nur __declspec(dllexport) dort stehen habe, habe ich es der lesbarkeit wegen rausgelassen.
    ist immer so ein ding mit dem vereinfachen... 😉



  • mael15 schrieb:

    jup, dieses konstrukt verwende ich auch. da der fehler derselbe ist wenn ich direkt nur __declspec(dllexport) dort stehen habe, habe ich es der lesbarkeit wegen rausgelassen.
    ist immer so ein ding mit dem vereinfachen... 😉

    Ok, dann könnte das auch das Problem sein. Du brauchst ja im Prinzip zwei Header: Einmal zum Builden der DLL und einmal zum Verwenden. Die Ausgabe des Vorkompilierens ist sehr wahrscheinlich von den definierten Makros dann abhängig und das Definieren oder Weglassen von BUILD_LIBDF hätte dann gar keinen Einfluss mehr. Zum Beispiel: Der, der die den Header und die DLL verwenden will, liest die für das DLL-Building erzeugte und vorkompilierte Version, in der BUILD_LIBDF definiert war und sieht dann ein dllexport was eigentlich ein dllimport hätte sein müssen. Das ist jetzt Spekulation, weil ich mich mit dem PCH-Kram, wie gesagt, nicht auskenne.



  • das problem ist gelöst.
    es sieht so aus, als hätte visual studio 2010 eine grundeinstellung gehabt, die präkompilierte header ermöglichte, ohne dass ich das jemals hätte einstellen müssen. bei vs 2012 war das nun nicht mehr der fall, ich musste also nur basic einstellungen für präkompilierte header nach folgender anleitung erstellen:
    http://manski.net/2011/11/09/precompiled-headers/#compiling_the_header

    erstaunlicherweise lief es vorher jahrelang ohne stdafx.h. 😕
    danke für eure ideen!


Anmelden zum Antworten