DLLs richtig erstellen und einbinden, wie?



  • Hallo zusammen,

    ich möchte eine kleine Lib schreiben, die sowohl auf Linux (GCC) als auch auf Windows (VC++) compiliert werden kann. Für Linux funktioniert das alles ohne Probleme, nur unter Visual Studio (Super IDE) gibt es Mal wieder Probleme (das Hauptproblem sitzt aber eher zwischen Bildschirm und naja du weist schon :D)

    Ich möchte einfach nur ein Projekt erstellen, welches eine DLL ist und ein zweites Projekt, welches eine simple Konsolanwendung ist und diese DLL nutzt. Dabei sollen beide Projekte in einer Projektmappe zusammengefasst sein. Als Versuch habe ich diesen DLL Code:

    #ifndef shared
    	#ifdef _WIN32
    		#define shared __declspec(dllimport)
    	#else
    		#define shared
    	#endif
    #endif
    // -- .h(pp)
    class shared Test
    {
    private:
    	int c;
    
    public:
    	Test()
    	{
    		c = 0;
    
    		//std::cout << "Test is constructing ... " << std::endl;
    	}
    
    	int getC();
    
    	virtual ~Test()
    	{
    		//std::cout << "Test is destructing ... " << std::endl;
    	}
    };
    // -- .cpp
    int Test::getC()
    {
    	return this->c++;
    }
    

    Und diesen Konsolapp Code:

    #include <iostream>
    #include <string>
    
    #include "Test.hpp"
    
    using namespace std;
    
    int main(int argc, char** argv, char** envp)
    {
    
    	Test t;
    
    	for (int i = 0; i < 10; i++)
    		cout << to_string(t.getC()) << endl;
    
    	cin >> argc;
    
    	return 0;
    }
    

    Das DLL Projekt ist im Konsol-Projekt als Verweis eingebunden, das Include Verzeichnis ist hinzugefügt, eben so wie der .lib Eintrag. Beide kompilieren in die gleichen Verzeichnisse hinein, daher ist mir unklar ob ich den Bibliothekspfad setzen muss.

    Beim Kompilieren der DLL bekomme ich diese Ausgabe:

    1>------ Erstellen gestartet: Projekt: AceSockLib, Konfiguration: Release x64 ------
    1> Test.cpp
    1>Test.cpp(4): warning C4273: "Test::getC": Inkonsistente DLL-Bindung.
    1> c:\users\vikto\onedrive\dokumente\c++\acesocklib\acesocklib\Test.hpp(19): note: Siehe vorherige Definition von "getC"
    1> Bibliothek "C:\Users\vikto\OneDrive\Dokumente\C++\AceSockLib\x64\Release\AceSockLib.lib" und Objekt "C:\Users\vikto\OneDrive\Dokumente\C++\AceSockLib\x64\Release\AceSockLib.exp" werden erstellt.
    1> Code wird generiert.
    1> 0 of 1 functions ( 0.0%) were compiled, the rest were copied from previous compilation.
    1> 0 functions were new in current compilation
    1> 0 functions had inline decision re-evaluated but remain unchanged
    1> Codegenerierung ist abgeschlossen.
    1> AceSockLib.vcxproj -> C:\Users\vikto\OneDrive\Dokumente\C++\AceSockLib\x64\Release\AceSockLib.dll
    ========== Erstellen: 1 erfolgreich, 0 fehlerhaft, 0 aktuell, 0 übersprungen ==========

    Und beim kompilieren des gesammten Projektes dann diese Ausgabe:

    Schweregrad Code Beschreibung Projekt Datei Zeile Unterdrückungszustand
    Fehler LNK1181 Eingabedatei "AceSockLib.lib" kann nicht geöffnet werden. AceSockLibDevDemo C:\Users\vikto\OneDrive\Dokumente\C++\AceSockLib\AceSockLibDevDemo\LINK 1
    Warnung C4273 "Test::getC": Inkonsistente DLL-Bindung. AceSockLib C:\Users\vikto\OneDrive\Dokumente\C++\AceSockLib\AceSockLib\Test.cpp 4

    Ich kann mit der Fehlermeldung und der Warnung nur leider nichts anfangen.



  • Wenn ich das Bibliotheksverzeichnis angebe, dann kommt diese Ausgabe:

    Schweregrad Code Beschreibung Projekt Datei Zeile Unterdrückungszustand
    Fehler LNK2019 Verweis auf nicht aufgelöstes externes Symbol ""__declspec(dllimport) public: __thiscall Test::Test(void)" (__imp_??0Test@@QAE@XZ)" in Funktion "_main". AceSockLibDevDemo C:\Users\vikto\OneDrive\Dokumente\C++\AceSockLib\AceSockLibDevDemo\main.obj 1
    Warnung C4273 "Test::getC": Inkonsistente DLL-Bindung. AceSockLib c:\users\vikto\onedrive\dokumente\c++\acesocklib\acesocklib\test.cpp 4
    Fehler LNK2019 Verweis auf nicht aufgelöstes externes Symbol ""__declspec(dllimport) public: virtual __thiscall Test::~Test(void)" (__imp_??1Test@@UAE@XZ)" in Funktion "_main". AceSockLibDevDemo C:\Users\vikto\OneDrive\Dokumente\C++\AceSockLib\AceSockLibDevDemo\main.obj 1
    Fehler LNK1120 2 nicht aufgelöste Externe AceSockLibDevDemo C:\Users\vikto\OneDrive\Dokumente\C++\AceSockLib\Debug\AceSockLibDevDemo.exe 1



  • Irgendwie musst du dem Compiler sagen was er überhaupt aus der DLL exportieren soll...

    Du musst also dafür sorgen dass das shared Marko folgendermassen definiert ist während die DLL übersetzt wird:

    #define shared __declspec(dllexport)
    

    Und BTW: nur "shared" ist kein guter Name für ein Makro in einem "öffentlichen" Header File.

    Die übliche Variante wäre

    #ifdef _WIN32
        #ifdef FOO_BUILDING
            #define FOO_SHARED __declspec(dllexport)
        #else
            #define FOO_SHARED __declspec(dllimport)
        #endif
    #else
        #define FOO_SHARED
    #endif
    

    Und dann im Projekt für die DLL einstellen dass das Makro FOO_BUILDING beim Übersetzen definiert ist (Projekteinstellungen, Preprocessor, Preprocessor Definitions).


Anmelden zum Antworten