Linker Error LNK2019: unresolved external symbol



  • Hallöchen Leute,

    mir ist bewusst das es solch einen Thread schon gibt aber da ich nun schon seid mehreren Stunden nach einer Lösung suche und erfolglos bin versuch ichs jetzt eben wie jeder andere mit einem eigenen Thread.

    Mein Problem:

    Ich bekomme folgenden Linker Error und diesen 54 mal für 54 Funktionen.

    1st Output Err:

    1>CTMDIG50IO_UMD.obj : error LNK2019: unresolved external symbol __imp__Dig50IO_enableInstrument referenced in function "public: int __thiscall CTMDIG50IO_UMD::enableInstrument(int)" (?enableInstrument@CTMDIG50IO_UMD@@QAEHH@Z)
    

    Da ich beim langen Suchen immer darauf gestoßen bin das mir evtl eine .lib Datei im Input bei dem Linker fehlt, ich aber keine .lib Datei habe bin ich eher am Verzweifeln.

    Was ich auch gelesen hab ist das ich den lib und include path setzen soll in den Directories aber das hatte ich bereits.

    Ich weiß einfach nicht was diese Linkererrors noch auslösen könnte -.-

    Hier einfach mal die Funktion auf die der Error deutet:

    .h

    #ifdef DIG50IO_INTERFACE_LIB
    	# define DIG50IO_INTERFACE_EXPORT __declspec(dllexport)
    #else
    	# define DIG50IO_INTERFACE_EXPORT __declspec(dllimport)
    #endif
    
    DIG50IO_INTERFACE_EXPORT KtError_t __cdecl  Dig50IO_enableInstrument(IN uint32_t u32_deviceHandle, IN const bool_t b_enable);
    

    .cpp

    KtError_t CTMDIG50IO_UMD::enableInstrument(const bool_t b_enable)
    {
    	KtError_t status = KT_ERROR_VI_NONE;
    
    	status = Dig50IO_enableInstrument(mu32_deviceHandle, b_enable);
    
    	return ERR_LOG(status);
    }
    

    Hoffe ihr habt noch paar gute Ideen. Heißt ja hier net umsonst, "Irgendwer hat immer eine Antwort" 😉



  • Der Linker beklagt sich, das er die Funktion Dig50IO_enableInstrument(..) nicht auflösen kann.

    Wie es aussieht steckt diese Funktion in der DLL.
    Die zugehörige LIB einzubinden wäre die einfachste Lösung.

    Wenn die LIB nicht vorhanden ist, gibt es die Möglichkeit die DLL mit

    HMODULE hModule = LoadLibrary(...)

    zu laden und die entsprechende Einsprungstelle mit

    Dig50IO_enableInstrument = GetProcAdress(hModule , "Dig50IO_enableInstrument");

    selbst aufzulösen. Um dem Compiler das als Funktion zu verkaufen muss vorher noch ein entsprechendes typedef das ganze definieren (siehe MSDN GetProcAdress).

    Es wäre zudem auch sinnvoll sich mal den Inhalt der DLL mit einem Texteditor anzusehen und zu prüfen ob die Funktion da wirklich so drin steht, oder ob noch was aus der C++ Ecke dran hängt.



  • Hey danke erstmal für deinen Beitrag 🙂 aber leider habe ich hierfür keine lib 😞

    Und was das HMODULE angeht weiß ich jetzt nicht wirklich wie ich genau vorgehen muss. Könntest du mir das evtl anhand eines Codes zeigen oder so?

    peace Adi


  • Mod

    Du solltest erst einmal herausbekommen in welcher DLL dieses Funktion denn definiert ist.
    Dann kannst Du genauso vorgehen, wie merano es beschirben hat.

    LoadLibrary ausführen und Du hast Dein HMODULE (besser HINSTANCE),
    dann GetProcAddress ausführen undDu hast Deine Funktionsadresse.

    Lies noch mal die Doku von Deinem Tool was Du ansprechen willst und schua mal nach ob es nicht dich eine LIB gibt. Wenn Du schon solch einen Header hast muss es auch eine entsprechende LIB geben.



  • Jaaa ich hab eine Lib gefunden und nun geht es ^^"

    Musste sie nur im Linker -> Input einbinden. Komischerweiße nimmt der den Pfad nicht an wenn ein Ordner im Namen ein Leerzeichen enthält.

    Jetzt bekomm ich lediglich noch 42 Warnings x____X Vllt könnt ihr mir da auch grad nen Tipp geben.

    ctmdig50io_umd.cpp(51) : warning C4700: uninitialized local variable 'mu32_deviceHandle' used
    

    Und das halt für jede Funktion in der .cpp

    Beispielfunktion aus der .cpp

    KtError_t initialize(const uint32_t u32_sequencerType)
    {
    	KtError_t status = KT_ERROR_VI_NONE;
    	uint32_t mu32_deviceHandle;
    
    	status = Dig50IO_initialize(mu32_deviceHandle, u32_sequencerType);
    
    	return ERR_LOG(status);
    }
    

    Bezug zur DIG50IO_initialize Funktion - .h

    DIG50IO_INTERFACE_EXPORT KtError_t __cdecl Dig50IO_initialize(IN uint32_t u32_deviceHandle, IN const uint32_t u32_sequencerType);
    

    Und jetzt hab ich in der Beispielfunktion in der .cpp oben,

    uint32_t mu32_deviceHandle;
    

    hinzugefügt. Aber eig. sollte die Variable über eine .h übergeben werden. Aber ich hab davon nicht viel Ahnung.

    Die steht hier ganz unten dabei:

    class ITMDIG50IO
    {
    
    public:
    	virtual KtError_t initialize(IN const uint32_t u32_sequencerType) = 0;
    private:
    	ITMDIG50IO(void);
    	ITMDIG50IO(const ITMDIG50IO& theITMDIG50IO);
    	uint32_t mu32_deviceHandle;
    };
    

    Aber die wird aus dieser .h Datei nicht in der .cpp erkannt. Ich weiß nicht genau wie das mit dem Konstruktor läuft, wusste ich mal.

    Kann mir da jemand einen Tipp geben wie ich die Variable die ich in jeder Funktion einzeln hinzugefügt habe rausnehmen kann sodas alle funktionen in der .cpp sich auf die Varibale aus der .h beziehen?

    danke schonmal Adi


  • Mod

    1. Die Variable ist nicht initialisiert, das heißt Du hast ihr keinen Wert zugewiesen, was ja auch stimmt..
    2. Eine Header Datei wird per #include eingebunden.
    2. Lies bitte ein Tutorial. Dein Fragen sollten sich dann ganz von selber lösen 😉



  • Ich hab das Header file included 😉

    Joa wenn ich den Variablen aus den Funktionen nen Wert zuweise dann verschwinden die Warnings.

    Aber im Grunde würd ich gerne alle Variablen aus jeder Funktion rausnehmen und die eine aus der Header Datei nutzen. Jedoch wird die iwie in der .cpp nicht erkannt 😞



  • Der Compiler sollte die Variable schon finden - dir aber auch gleichzeitig sagen, daß du sie nicht nutzen darfst (weil sie privat in der Basisklasse ist, dürfen nur Methoden der Basisklasse darauf zugreifen).

    Btw, irgendwie erschließt sich mir der Sinn nicht ganz, eine abstrakte Klasse ohne nutzbare Konstruktoren zu definieren. Objekte dieser Klasse kannst du mit der pur virtuellen Methode ohnehin nicht erstellen, aber ohne einen protected oder public-Konstruktor kannst du auch keine Objekte abgeleiteter Klassen erstellen.



  • Wenn die Methode Teil einer Klasse ist müsste die Funktion (Methode) eigentlich so implementiert werden:

    KtError_t ITMDIG50IO::initialize(const uint32_t u32_sequencerType) {
       KtError_t status = KT_ERROR_VI_NONE; 
       status = Dig50IO_initialize(mu32_deviceHandle, u32_sequencerType);
    
       return ERR_LOG(status); 
    }
    

    Die Member-Variable mu32_deviceHandle ist ja im Objekt vorhanden.

    Der deviceHandle sollte eigentlich im Konstruktor initialisiert worden sein. 🙂



  • Der private Konstruktor könnte bedeuten, das es nur eine Instanz geben darf.

    siehe:
    http://de.wikipedia.org/wiki/Singleton_(Entwurfsmuster)

    Das würde in diesem Fall evtl. auch Sinn machen, da es sich offensichtlich um eine Hardwareschnittstelle handelt.


Anmelden zum Antworten