Dynamische Bibliothek mit C++



  • Hiho,

    ich kenne mich mit C++ zwar generell ganz passabel aus, aber beim dynamischen Linken habe ich eine riesige Bildungslücke :S

    Also ich möchte mit C++ eine dynamische Bibliothek schreiben, die ich sowohl unter Windows als auch unter GNU/Linux benutzen kann (jeweils neu kompiliert, versteht sich). Ich habe nun hpp und cpp Dateien, die ich alle in eine dynamische Bibliothek packen möchte. Mein CMake sieht so aus:

    set( BUILD_SHARED_LIBS ON )
    file( GLOB_RECURSE spark_srcs src/*.cpp )
    add_library( spark ${spark_srcs} )
    

    Überraschenderweise funktioniert das einwandfrei auf Windows MinGW-w64, wobei ich doch normalerweise dachte, man muss __declspec Zeug einfügen?

    Meine Fragen:
    1. Wieso klappt das auch ohne das __declspec Zeug? Was ist der Nachteil ohne das?
    2. Ist das plattformunabhängig? Kann ich davon ausgehen, dass jeder gängige Compiler die Bibliothek korrekt kompiliert?
    3. Ich habe im Internet kurz etwas von name mangling gelesen und dass es ein Problem sei. Die Lösungen dort waren ganz obskur, mit extern "C" und Factories etc. Nun möchte ich natürlich nicht für jede einzelne Klasse eine Factory schreiben müssen, also wieso wird das angepriesen?

    MFG



  • Hallo,

    1. Das klappt weil MinGW alle Symbole standardmäßig exportiert. Der Compiler hängt also die notwendigen Spezifikationen an. Microsoft Compiler machen das z. Bsp. nicht. Da musst du jedes Symbol selber exportieren.
    2. Da ich den Quelltext der Bibliothek nicht kenne kann ich dazu nichts sagen. probiers aus.
    3. Die einzelnen Compiler verwenden manchmal verschiedene Arten des Namen der exportierten Symbole zu bilden. Das führt dann dazu, das man auf einem Compiler kompilierte dynamische Libs nur mit Programmen lesen kann die mit dem gleichen Compiler erzeugt wurden. Es kann auch mit anderen gehen ist aber nicht sicher. Um das Problem zu umgehen verwenden manche Leute die extern "C" Spezifikation. Hier wird alles als reiner C-Code behandelt. das ist standardisiert und funktioniert auf allen Compilern. So kriegst du natürlich keine Klassen nach draußen.



  • Bezüglich verschiedener Compiler sei auch noch erwähnt, dass diese abseits von unterschiedlichem Name Mangling auch noch teilweise verschiedene Implementationen oder Versionen der Standardbibliothek verwenden, oder Objekte ein anderes Speicherlayout haben können. Virtuelle Vererbung kann z.B. sehr unterschiedlich implementiert sein, und auch bezüglich Padding lässt der Standard diverse Freiheiten, wie ein Objekt letztendlich exakt im Speicher aussieht.

    Das alles führt zu der Problematik, dass Programme sehr wahrscheinlich nicht mit dynamischen C++-Bibliotheken funktionieren werden, wenn diese mit einem anderen Compiler gebaut wurden (oder teilweise auch mit dem selben Compiler und nur mit anderen Compiler-Einstellungen), es sei denn man beschränkt sich auf ein minimales C-Interface und verwendet an der Schnittstelle lediglich POD-Strukturen.

    Das bedeutet z.B. keine Bibliotheksfunktionen, die beispielsweise einen std::string , std::vector oder ähnliches als Parameter entgegennehmen, nicht einmal selbtgebaute Klassen wenn man wirklich maximale Kompatibilität sicherstellen will. Der Grund dafür ist, dass innerhalb der mit Compiler B gebauten Bibliotheksfunktion ein anderes Spiecherlayout oder gar einer völlig andere Implementierung des übergebenen Objekts erwartet wird, als der mit Compiler A gebaute Programmcode konstruiert hat und der Bibliotheksfunktion übergibt.

    Davon abgesehen - wenn man akzeptiert dass Programm(e) und Dynamische Bibliotheken immer eine Einheit bilden, und gemeinsam mit dem selben Compiler und identischen Flags kompiliert werden müssen, funktionert das meiner bisherigen Erfahrung nach plattform- und systemübergreifend recht gut und ohne viel Kopfzerbrechen. Zu deiner Frage 2.: Ich gehe davon aus, dass dieses CMake-Konstrukt "plattformunabhängig" funktioniert, zumindest für alle Plattformen und Compiler die von CMake unterstützt werden. Mit CMake habe ich damit zumindest unter Linux und Windows mit MSVC, GCC und Clang bisher noch keine gegenteiligen Erfahrungen gemacht.

    Finnegan


Log in to reply