[gelöst] brauche Hilfe mit template methoden



  • Hallo,

    ich bin schon seit 24h am ausprobieren und komme langsam nicht mehr weiter.

    Worum es geht:
    Ich möchte eine allgemeine Lösung finden wie man am besten DLL dynamisch einbindet. Naürlich habe ich das schon "konventionel" geschafft und möchte jetzt so eine Art Vorlage für zukünftige Projekte schreiben.
    Dazu habe ich 3 Projecte im ProjectOrdner erstellt:

    application.exe
    interface.lib
    calculator.dll

    Bevor jetzt einer denkt es gehe um WinAPI und aufhört zu lesen,da falsches Forum möchte ich schnell sagen das dem nicht so ist und um Geduld bitten. Vieleicht kann man mir besser helfen wenn man weiß worum es geht.

    Ich habe vereinfacht folgenden code:

    application
    main.cpp

    #include "INTERFACE.h"
    #include "DLL_MANAGER.h"
    #include <iostream>
    using namespace std;
    
    int main()
    {
    	iiDLL_MANAGER iDevice;
    	iiCALCULATOR_INTERFACE *calculatorDevice = 0;
    
    	iDevice.LoadEngineDevice(L"multiply.dll");
    	iDevice.GetDeviceHandle(calculatorDevice);
    	calculatorDevice->Multiply(4, 4);
    	calculatorDevice->Devide(10, 2);
    }
    

    interface
    INTERFACE.h //abstrakte Klasse

    #pragma once
    class iiCALCULATOR_INTERFACE
    {
    public:
    	virtual int Multiply(int, int) = 0;
    	virtual int Devide(int, int) = 0;
    	virtual void Release() = 0;
    };
    
    extern "C" __declspec(dllexport) 
    	iiCALCULATOR_INTERFACE *GetInterfaceImplementation();
    

    immernoch
    interface
    DLL_MANAGER.h

    #pragma once
    #include <windows.h>
    
    class iiDLL_MANAGER
    {
    public:
    	iiDLL_MANAGER(void);
    	~iiDLL_MANAGER(void);
    
    	void	LoadEngineDevice(LPCWSTR libraryName);
    
            template<typename T>
    	void	GetDeviceHandle(T deviceType);              //darum geht es
    	void	ReleaseEngineDevice();
    private:
    	HMODULE hDll;
    };
    

    interface
    DLL_MANAGER.cpp

    #include "iiDLL_MANAGER.h"
    #include <iostream>
    using namespace std;
    
    iiDLL_MANAGER::iiDLL_MANAGER(void)
    {
    }
    
    iiDLL_MANAGER::~iiDLL_MANAGER(void)
    {
    }
    
    void iiDLL_MANAGER::LoadEngineDevice(LPCWSTR libraryName)
    {	       hDll=0;																
    hDll=LoadLibrary(libraryName);										
    cout<<"Loading library was successful.\n"	
    }
    
    template<typename T>
    void iiDLL_MANAGER::GetDeviceHandle(T deviceType)
    {
       	T deviceType = (T)GetProcAddress(hDll, "GetInterfaceImplementation");
    }
    
    void         iiDLL_MANAGER::ReleaseEngineDevice()
    {
        //TODO
    }
    

    calculator
    SLOW_CALCULATOR.h

    #pragma once
    #include "iiCALCULATOR_INTERFACE.h"
    #include <iostream>
    
    class iiSLOWCALCULATOR : public iiCALCULATOR_INTERFACE  
    {
    public:
    	iiSLOWCALCULATOR(void);
    	~iiSLOWCALCULATOR(void);
    
    	int Multiply(int factor1, int factor2);
    	int Devide(int devident, int devisor);
    	void Release();
    };
    

    calculator
    SLOW_CALCULATOR.cpp

    #include "iiSLOWCALCULATOR.h"
    
    iiSLOWCALCULATOR::iiSLOWCALCULATOR(void)
    {
    }
    
    iiSLOWCALCULATOR::~iiSLOWCALCULATOR(void)
    {
    }
    
    int iiSLOWCALCULATOR::Multiply(int factor1, int factor2)
    {
    	std::cout<<factor1*factor2 <<std::endl;
    	return (factor1 * factor2);										
    }
    int iiSLOWCALCULATOR::Devide(int devident, int devisor)
    {
    	std::cout<<devident/devisor <<std::endl;
    	return (devident/devisor);
    }
    void iiSLOWCALCULATOR::Release()
    {
    	delete this;
    }
    
     iiCALCULATOR_INTERFACE *GetInterfaceImplementation()         //!!!
    {
    	return new iiSLOWCALCULATOR;
    }
    

    Jetzt noch schnell die Fehlermeldung:

    3>ClCompile:
    3> main.cpp
    3>main.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""public: void __thiscall iiDLL_MANAGER::GetDeviceHandle<int>(int)" (??$GetDeviceHandle@H@iiDLL_MANAGER@@QAEXH@Z)" in Funktion "_main".
    3>C:\Dokumente und Einstellungen\Ghost\Eigene Dateien\Visual Studio 2008\Projects\dynamik DLL link\Debug\application.exe : fatal error LNK1120: 1 nicht aufgelöste externe Verweise.
    3>
    3>Fehler beim Erstellen
    3>
    3>Verstrichene Zeit 00:00:02.43
    ========== Alles neu erstellen: 2 erfolgreich, Fehler bei 1, 0 übersprungen ==========

    Mein Problem ist allem Anschein nach die template Funktion da es keinerlei Probleme gibt wenn ich diese Funktion fest "verdrahte". Mein gedanke war aber das ich die Klasse DLL_MANAGER für alle INTERFACE typen benutzen kann.
    Ich übergebe also den Dateinamen und einen Zeiger des Zieltyps - die dll wird geladen und der Zeiger mit der Adresse des erstellten Objects initialisiert.

    Ich möchte nochmals sagen dass es mir nicht um das laden der dll geht sondern wie ich die template funktion richtig nutze.

    Vielen Dank

    Gruß



  • Wozu Templates? Du hast doch deine Basisklasse, also kannst du doch einfach in jeder deiner Libs eine Methode "GetDeviceImplementation" definieren, die einen Pointer auf ein iiCALCULATOR_INTERFACE zurückgibt. Die Methode erstellt dann ein neues Objekt des jeweiligen Typen und du kannst ganz normal auf die Methoden zugreifen. Beispiel:

    base.h

    class base
    {
        public:
            virtual void doSomething() = 0;
    };
    
    extern "C" base *getInstance();
    

    derived.h

    class derived : public base
    {
        public:
            void doSomething();
    };
    

    derived.cpp (wird als statische/dynamische Lib kompiliert)

    void derived::doSomething()
    {
        std::cout << "derived";
    }
    
    base *getInstance()
    {
        return new derived;
    }
    

    Bei einer statischen Lib könntest du dann in einem Projekt folgendermaßen drauf zugreifen:

    int main()
    {
        base *d = getInstance();
    
        d->doSomething(); // gibt "derived" aus
    
        delete d;
    
        return 0;
    }
    


  • aber dann müsste CALCULATOR_INTERFACE alle interface funktionen enthalter auch die von z.B.: AUDIO_INTERFACE.
    Ich möchte zu jeder DLL eine interface KLasse schleiben von der dann geerbt wird und die dann überschrieben wird.
    Ich möchte mit dem DLL_MANAGER auch AUDIO_INTERFACE usw. laden können.

    Kannst du denn erkennen warum ein linkfehler entsteht?



  • Template-Definitionen müssen im Header platziert werden, da sonst der Linker diese Funktionen nicht kennen kann (und daher auch die Fehlermeldung kommt).

    Richtig also:

    // in DLL_MANAGER.h
    
    template<typename T>
    void iiDLL_MANAGER::GetDeviceHandle(T deviceType)
    {
      T deviceType = (T)GetProcAddress(hDll, "GetInterfaceImplementation");
    }
    

    Entweder direkt in der Klasse definieren (ohne 'iiDLL_MANAGER::') oder aber unterhalb der Klasse anordnen bzw. sogar in eigene Datei 'dll_manager.inl' auslagern und unten in der Headerdatei ein

    #include "dll_manager.inl"
    

    s.a. FAQ: Template in Header und Source aufteilen



  • Ja alles klar das war der Fehler.
    Danke.



  • Devide -> Divide



  • @padreigh danke, sehr aufmerksam.


Anmelden zum Antworten