[DLL] Anfängerfragen zu static/shared/dynamic link libraries



  • Hallo liebe Gemeinde,

    ich habe einige Verständnisfragen zum Thema shared libraries und hoffe, dass ich damit nicht ein tausend mal besprochenes Thema angehe (die Suche half wenig bis gar nicht).

    1. Es gibt ja .lib/.a und .dll/.so, je nach Compiler und je nach OS. Die ersten beiden sind soweit ich das verstehe statische Bibliotheken, die mit dem Programm zusammen compiliert werden bzw. gelinkt werden. Das bedeutet für mich, dass ich bei diesen beiden das Programm neu compilieren muss, wenn ich bspw. einen Fehler ausmerze oder irgendwas anderes am Code ändere, was aber ansonsten nur die Libs und nicht das Programm an sich betrifft. Stimmt das so?

    2. .dll/.so sind ja dynamische Bibliotheken. Bedeutet, dass ich mir eine davon erstellen kann und dann über LoadLibrary/GetProcAddress bzw. dlopen/dlsym die nötigen Funktionen in mein Programm hole. Dass ich dann ohne Auswirkungen meine dynamische Bibliothek ändern kann, erscheint mir hier am logischten (natürlich muss sie dann auch abwärtskompatibel bleiben). Liege ich da richtig?

    3. Bei einigen .dll/.so liegen neben den .h-Dateien auch noch .lib/.a-Dateien bei. Wenn ich jetzt aber mir ein Programm erstelle, dass mit der .lib/.a-Datei gelinkt wurde, dann kann ich die .dll/.so doch gar nicht mehr einfach ändern, oder? Wie bekomme ich denn ansonsten hin, dass ich ohne LoadLibrary/GetProcAddress bzw. dlopen/dlsym die Funktionen der .dll/.so aufrufen kann und trotzdem in der Lage bin die dynamische Bibliotheken zu ändern ohne mein Programm neu compilieren zu müssen?

    4. Muss ich eine .lib/.a-Bibliothek für jeden Compiler nach Bedarf compilieren oder kann ich die beliebig linken? Bei manchen Downloads ist nämlich das ganze Verzeichnis dabei um die Datei zu linken und bei anderen ist nur eine .lib/.a-Datei + Header. Wie könnte man denn in dem Fall anderen Nutzern die Bibliothek zugänglich machen ohne den Quellcode preis geben zu müssen? Sollte man dann für jede Möglichkeit eine extra .lib/.a vorcompiliert mitgeben (unwahrscheinlich) oder wie macht man das stattdessen?

    5. Ich habe mal gelesen, dass der Export von Klassen schwierig sein soll. Woran liegt das? Mir ist das bisher nicht aufgefallen. Könnte ich eine .dll/.so mit einer Klasse auch unter reinem C verwenden (nur ohne Klasse natürlich)?

    Vielen Dank schonmal 🙂



  • Es gibt noch eine dritte Möglichkeit:
    Wenn du dynamisch linkst, dann benötigt der Compiler die Headerdatei und der Linker die .lib/.a-Datei, aber zur Laufzeit wird dann die .dll/.so-Datei herangezogen (so daß du diese im Nachhinein austauschen kannst, ohne das Hauptprogramm neu kompilieren zu müssen).

    Und zu deiner letzten Frage:
    reine C++ Libraries (d.h. ohne 'extern "C"') können von C aus nicht direkt verwendet werden (u.a. wegen dem Name mangling), sondern dann muß man sog. Wrapper erstellen.



  • Vielen Dank soweit.

    Was steht denn dann aber bei den Libs drin? Sind das nur Verweise oder ist da ansich auch der tatsächliche Code, der für die Funktionen benötigt werden? Woher weiß dann das Programm, welchen Code (also den von der .lib/.a oder von der .dll/.so) er verwenden soll?



  • Bei mir ist noch eine Frage aufgekommen.
    Kann ich, wenn ich ein Makro in einer Header-Datei definiere, die durch die DLL genutzt wird, in einem späteren Programm das Makro ausstellen, so dass die DLL das mitbekommt?

    Also als Beispiel:

    // Funktion in der DLL:
    void echo (char* string) {
        msg ("echo: ");
        printf (string);
    }
    
    // das steht im Header der DLL und wird mit compiliert
    #ifdef QUIET
    #define msg(X)
    #else
    #define msg(X)    printf(X);
    #endif
    
    // rufe ich jetzt in meinem Programm, welches die DLL nutzt echo() auf, gibt es eine Ausgabe + Zusatz
    echo ("Hallo Welt");  //Ausgabe: "echo: Hallo Welt"
    
    // jetzt möchte ich bei echo() aber keine Zusatz-Ausgabe mehr haben, also definiere ich QUIET
    #define QUIET
    echo ("Hallo Welt"); //Ausgabe: "Hallo Welt"
    

    Gibt es da eine Möglichkeit? Andernfalls müsste ich zwei DLL's erstellen, einmal mit definiertem Makro, einmal ohne. Das wäre sehr schade und recht aufwendig, wenn mal etwas geändert werden muss.

    Vielen Dank!



  • Hi, ich glaube, Du befindest Dich grundlegend im Irrtum, was das mit den Macros anbelangt.
    Die werden VOR dem eigentlichen Compilieren vom Präprozessor rein durch textuelles Ersetzen aufgelöst, erst dann legt der Compiler los, deswegen heißt der Präprozessor auch so.
    Das geht auch bis zu einem gewissen Grad nested bis zu einer Tiefe, die aber vom Compilerbauer abhängt, aber nach dem Präprozessorlauf liegt nur EINE Version der expandierten Source vor, die dann wirklich übersetzt wird.

    Zur Laufzeit kann sich da gar nichts mehr ändern und auch schon nicht zur Compiletime.
    Gib' Dir mal den GCC- Überblick zu Macros, besonders die Pitfalls! 😮
    Auch lesenswert: https://en.wikipedia.org/wiki/X_Macro und http://www.embedded.com/design/programming-languages-and-tools/4403953/C-language-coding-errors-with-X-macros-Part-1
    Bemühe einfach eine Suchmaschine Deines Vertrauens und behalte im Hinterkopf, daß nur EINE Version pro Compilerlauf tatsächlich gebaut wird. Da könntest Du über einen define festlegen, ob gerade die geschwätzige oder stille Version gebaut werden soll.

    Ochja, ich weiß zwar nicht warum, aber Macro- Tricksereien (und davon gibt es ein paar) gelten als verpönt und machen tatsächlich selten etwas lesbarer.



  • pointercrash() hat das Problem bzgl. Macros schon eingehend erklärt.

    sodll schrieb:

    Gibt es da eine Möglichkeit?

    Was du statt dessen machen könntest, wäre halt eine stink normale Funktion schreiben und die entscheidet dann anhand eines Ini-Datei-Eintrags, ob du die zusätzliche Ausgabe mit ausgibst.
    Nachteil wäre halt, du hast eine zusätzliche Config-Datei, bzw. Ini-Datei ("MyIniFile.ini") herumliegen und die haben, zumindest bei uns, die blöde Eigenschaft, dass diese Dateien mit Einträgen über die Zeit zu wuchern.

    // code ist ungetestet und einfach im Forum eingetippt (quasi Pseudocode)
    void echo (char* string) {
        int extendedOutput = GetPrivateProfileInt(L"Debug",L"ExtendedOutput", 0, L"MyIniFile.ini");
        if(extendedOutput == 1)
        {
          printf("echo: ");
        }
        printf (string);
    }
    

    Dann hättest du tatsächlich nur 1 DLL und könntest die Zusatzausgabe alleine über die Ini-Datei steuern. Einfach eine entsprechende Section + Key in die Ini-Datei schreiben und gut ist.

    [Debug]
    ExtendedOutput=1


Log in to reply