Exportieren und Importieren mithilfe von AFX_EXT_CLASS
MFC-Erweiterungs-DLLs (Dynamic Link Library) verwenden das Makro AFX_EXT_CLASS zum Exportieren von Klassen. Die ausführbaren Dateien, die mit der MFC-Erweiterungs-DLL verknüpft sind, verwenden das Makro, um Klassen zu importieren. Mit dem Makro AFX_EXT_CLASS können die gleichen Headerdateien, die zum Erstellen der MFC-Erweiterungs-DLL verwendet werden, mit den ausführbaren Dateien verwendet werden, die mit der DLL verknüpft sind.
Fügen Sie in der Headerdatei für die DLL der Deklaration der Klasse das AFX_EXT_CLASS-Schlüsselwort wie folgt hinzu:
class AFX_EXT_CLASS CMyClass : public CDocument
{
// <body of class>
};
Dieses Makro wird von der MFC als __declspec(dllexport)
definiert, wenn die Präprozessorsymbole _AFXDLL
und _AFXEXT
definiert werden. Das Makro wird jedoch als __declspec(dllimport)
definiert, wenn _AFXDLL
definiert und _AFXEXT
nicht definiert ist. Im Falle einer Definition gibt das Präprozessorsymbol _AFXDLL
an, dass die freigegebene MFC-Version von der ausführbaren Zieldatei verwendet wird (entweder eine DLL oder eine Anwendung). Wenn sowohl _AFXDLL
als auch _AFXEXT
definiert sind, gibt dies an, dass die ausführbare Zieldatei eine MFC-Erweiterungs-DLL ist.
Da AFX_EXT_CLASS
beim Exportieren aus einer MFC-Erweiterungs-DLL als __declspec(dllexport)
definiert ist, können Sie ganze Klassen exportieren, ohne die dekorierten Namen für alle Symbole dieser Klasse in der DEF-Datei abzulegen.
Obwohl Sie das Erstellen einer DEF-Datei und aller dekorierten Namen für die Klasse mit dieser Methode vermeiden können, ist das Erstellen einer DEF-Datei effizienter, da die Namen nach Ordinalzahl exportiert werden können. Fügen Sie den folgenden Code am Anfang und am Ende der Headerdatei ein, wenn Sie die DEF-Dateimethode für den Export verwenden möchten:
#undef AFX_DATA
#define AFX_DATA AFX_EXT_DATA
// <body of your header file>
#undef AFX_DATA
#define AFX_DATA
Achtung
Beim Exportieren von Inlinefunktionen müssen Sie vorsichtig vorgehen, da diese Versionskonflikte verursachen können. Eine Inlinefunktion wird in den Anwendungscode erweitert. Wenn Sie deshalb die Funktion später neu schreiben, wird sie erst dann aktualisiert, wenn die Anwendung selbst neu kompiliert wird. (In der Regel können DLL-Funktionen ohne Neuerstellung der Anwendungen aktualisiert werden, die diese verwenden.)
Exportieren einzelner Member in einer Klasse
Manchmal möchten Sie möglicherweise einzelne Member einer Klasse exportieren. Wenn Sie z. B. eine von CDialog
abgeleitete Klasse exportieren, müssen Sie möglicherweise nur den Konstruktor und den DoModal
-Aufruf exportieren. Sie können AFX_EXT_CLASS
für die einzelnen Member verwenden, die Sie exportieren müssen.
Beispiel:
class CExampleDialog : public CDialog
{
public:
AFX_EXT_CLASS CExampleDialog();
AFX_EXT_CLASS int DoModal();
...
// rest of class definition
...
};
Da Sie nicht mehr alle Member der Klasse exportieren, kann es aufgrund der Funktionsweise von MFC-Makros zu einem zusätzlichen Problem kommen. Mehrere MFC-Hilfsmakros deklarieren oder definieren Datenmember. Daher müssen diese Datenmember auch aus der DLL exportiert werden.
Beispielsweise wird das DECLARE_DYNAMIC
-Makro beim Aufbau einer MFC-Erweiterungs-DLL wie folgt definiert:
#define DECLARE_DYNAMIC(class_name) \
protected: \
static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
static AFX_DATA CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \
Die Zeile, die mit dem statischen Element AFX_DATA
beginnt, deklariert ein statisches Objekt in der Klasse. Wenn Sie diese Klasse ordnungsgemäß exportieren und auf die Runtimeinformationen einer ausführbaren Clientdatei zugreifen möchten, müssen Sie dieses statische Objekt exportieren. Da das statische Objekt mit dem Modifizierer AFX_DATA
deklariert ist, müssen Sie AFX_DATA
beim Erstellen Ihrer DLL nur als __declspec(dllexport)
und beim Erstellen der ausführbaren Clientdatei als __declspec(dllimport)
definieren. Da AFX_EXT_CLASS
bereits auf diese Weise definiert ist, müssen Sie AFX_DATA
wie AFX_EXT_CLASS
nur um Ihre Klassendefinition herum neu definieren.
Beispiel:
#undef AFX_DATA
#define AFX_DATA AFX_EXT_CLASS
class CExampleView : public CView
{
DECLARE_DYNAMIC()
// ... class definition ...
};
#undef AFX_DATA
#define AFX_DATA
Da die MFC immer das AFX_DATA
-Symbol für Datenelemente verwendet, die in den Makros definiert werden, funktioniert diese Technik für all diese Szenarios. Beispielsweise funktioniert es für DECLARE_MESSAGE_MAP
.
Hinweis
Wenn Sie die gesamte Klasse anstelle ausgewählter Member der Klasse exportieren, werden statische Datenmember automatisch exportiert.
Wie möchten Sie vorgehen?
Exportieren aus einer DLL mithilfe von „__declspec(dllexport)“
Exportieren von C++-Funktionen zur Verwendung in ausführbaren C-Dateien
Exportieren von C-Funktionen zur Verwendung in ausführbaren C- oder C++-Dateien
Importieren in eine Anwendung mithilfe von __declspec(dllimport)