Klassen in DLLs



  • Hallo,

    nachdem hier in letzter Zeit soviele DLL-Fragen aufauchen, hab ich auch noch eine...

    In Qt ist es ja ohne weiteres möglich, eigene deklarierte Klassen zu exportieren, also etwa:

    #ifndef MAP_HPP
    #define MAP_HPP
    
    #include <QtCore>
    #include <QtGui>
    
    #ifdef BUILD_MAP
    #define EXPORT_MAP Q_DECL_EXPORT
    #else
    #define EXPORT_MAP
    #endif
    
    class QXmlSimpleReader;
    class QXmlInputSource;
    
    class EXPORT_MAP Map : public QObject
    {
    public:
      Map( QObject* parent = 0);
    
    [...]
      loadMap( QIODevice* input);
    [...]
    }
    

    und Methoden der Klasse Map lassen sich dann aus anderen DLLs oder dem Hauptprogramm aufrufen.

    Bei der Deklarierung einer "normalen" Win32-DLL (nicht-MFC) habe ich aber bisher immer nur Funktionen gesehen, die exportiert werden (z.B. im Petzold):

    [...]
    #ifdef __cplusplus
    #define EXPORT extern "C" __declspec(dllexport)
    #else
    #define EXPORT __declspec(dllexport)
    #endif
    
    EXPORT BOOL CALLBACK EdrCenterTextA(HDC, RECT, PCSTR);
    EXPORT BOOL CALLBACK EdrCenterTextW(HDC, RECT, PCSTR);
    
    #ifdef UNICODE
    #define EdrCenterText EdrCenterTextW
    #else
    #define EdrCenterText EdrCenterTextA
    #endif
    

    und wie es aussieht, können ja nur extern "C"-Funktionen (ohne Name Mangling) exportiert werden.
    Wie sieht dass dann bei den o.g. Qt-/abgeleiteten Klassen aus (bei denen die Klassen/Methoden (z.B. die Methode Map::loadMap()) ja auf jeden Fall dem Name Mangling unterworfen werden)?

    Danke für alle Hinweise (ist jetzt kein konkretes Problem, mehr eine Verständnisfrage).

    AlGaN



  • du musst eine funktion exportieren, die dir eine neue klasseninstanz erstellt 🙂

    extern "C" EXPORTS Map *CreateMap()
    // in der dll
    {
        return new Map;
    }
    


  • und wie es aussieht, können ja nur extern "C"-Funktionen (ohne Name Mangling) exportiert werden.

    Das ist nicht korrekt. Es gibt mehrere Mögl. Dinge zu exportieren.
    Auch gemangelte Dinge können exportiert werden.

    Alles eine Frage davon was der Konsument erwartet und der Erstellrer zur Verfügung stellt.. muss einfach zusammenpassen.

    du musst eine funktion exportieren, die dir eine neue klasseninstanz erstellt

    Wenn das gemacht wird, muss auch wieder aufgeräumt werden und dass MUSS wieder in der DLL gemacht werden, welche das new aufgerufen hat. Also entweder analog zu CreateInstance(..) noch DeleteInstance(..) oder eine virtuelle destroy(..) Member Funktion.

    Eine häufige Variante Klassen zu exportieren ist so:
    1. Interface definieren (abstrakte Klasse, mit pure virtual's)
    2. Eine Impl. erstellen, welche das Interface impl. (in der DLL)
    3. Factory Funktionen (new / delete) erstellen (wie antwort! angemerkt hat)

    Der Client benötigt dann nur das Interface (welches er als Header File includiert) und nur das! In der exportierten Klasse steht dann rein gar nichts mehr dass sie exportiert wird (KEIN class EXPORT_MAP Map).

    Eine andere, weniger flexiblere Variante, ist die ganze Klasse mit dem __declspec(dllexport) zu markieren ( ➡ class EXPORT_MAP Map).
    Dann benötigt man aber keine Factory Funktionen. Jedoch darf das export makro nicht das namemangling unterbinden.

    Es macht kein Sinn, die Klasse mit dem __declspec(dllexport) zu markieren UND das namemangling auszuschalten.

    Es gibt noch viele andere Möglichkeiten.

    Simon


Anmelden zum Antworten