Freigeben über


TN033: DLL-Version von MFC

Dieser Hinweis wird beschrieben, wie Sie die gemeinsam genutzten Dynamic Link Librarys MFCxx.DLL und MFCxxD.DLL (wobei x die MFC-Versionsnummer) mit MFC-Anwendungen und Erweiterungs-DLLs verwenden können.Weitere Informationen zu regulären DLL finden Sie unter Verwenden von MFC als Teil einer DLL.

In diesem technischen Hinweis enthält drei Aspekte von DLLs.Die letzten beiden sind für die weitere fortgeschrittenen Benutzern verwendet:

  • So erstellen Sie eine MFC-Erweiterungs-DLL

  • So erstellen Sie eine MFC-Anwendung erstellen, die die DLL-Version von MFC verwendet

  • Wie die MFC gemeinsam genutzten Dynamic Link Libraries) implementiert werden

Wenn Sie bei der Erstellung interessiert sind, die mit MFC DLL mit MFC-fremden Anwendungen (diese eine reguläre DLL aufgerufen wird) verwendet werden kann, finden Sie unter Technischer Hinweis 11 an.

Übersicht über MFCxx.DLL-Unterstützung: Terminologie und Dateien

Regular DLL: Sie verwenden eine reguläre DLL, um ein eigenständiges DLL mithilfe einiger der MFC-Klassen zu erstellen.Schnittstellen App-/DLL über die Grenze sind "C" - Schnittstellen, und die Clientanwendung darf keine MFC-Anwendung sein.

Dies ist die Version von DLL-Unterstützung unterstützt in MFC 1.0.Es wird in Technischer Hinweis 11 beschrieben und das Konzept Erweiterte MFC Beispiel für eine DLLScreenCap.

HinweisHinweis

Ab Visual C++, Version 4.0, wird der Ausdruck USRDLL veraltet und wurde durch eine reguläre DLL ersetzt, die statisch mit MFC verknüpft.Erstellen Sie können auch eine reguläre DLL, die dynamisch mit MFC verknüpft.

MFC 3.0 (und höher) unterstützt reguläre DLL mit der gesamte neuen Funktionen einschließlich des OLE und die Datenbankklassen.

AFXDLL: Dies wird auch als freigegebene Version der MFC-Bibliotheken.Dies ist die neue DLL-Unterstützung, die in MFC 2.0 hinzugefügt wird.Die MFC-Bibliothek selbst ist in einigen DLL (unten beschrieben) und einer Clientanwendung oder DLL verknüpft die DLL dynamisch mit erfordert.Schnittstellen über die application-/DLL C++-/MFC klassenschnittstellen beschränkt sind.Die Clientanwendung eine MFC-Anwendung sein MUSS.Dies unterstützt alle Funktionen MFC 3.0 (Ausnahme: UNICODE wird nicht für die Datenbankklassen unterstützt).

HinweisHinweis

Ab Visual C++, Version 4.0, wird dieser DLL-Typ als eine Erweiterungs-DLL."

Dieser Hinweis verwendet, um den gesamten MFCxx.DLL MFC-DLL-Satz zuzugreifen, die Folgendes enthält:

  • Debuggen: MFCxxD.DLL (kombiniert) und MFCSxxD.LIB (statisch).

  • Version: MFCxx.DLL (kombiniert) und MFCSxx.LIB (statisch).

  • Unicode: Debug MFCxxUD.DLL (kombiniert) und MFCSxxD.LIB (statisch).

  • Unicode-Version: MFCxxU.DLL (kombiniert) und MFCSxxU.LIB (statisch).

HinweisHinweis

Die Bibliotheken MFCSxx [U] [D] .LIB werden zusammen mit der MFC-gemeinsamen genutztem DLL verwendet.Diese Bibliotheken enthalten Code, der in die Anwendung oder die DLL statisch verknüpft werden muss.

Links zu den entsprechenden einer Anwendung: Importbibliotheken

  • Debuggen: MFCxxD.LIB

  • Version: MFCxx.LIB

  • Unicode: Debug MFCxxUD.LIB

  • Unicode-Version: MFCxxU.LIB

Eine "MFC-Erweiterungs-DLL" ist eine DLL, die nach MFCxx.DLL erstellt wird (und/oder anderen MFC-gemeinsamen genutztem DLL).Hier wird die Architektur der in MFC-Teil.Wenn Sie eine nützliche Klasse aus einer MFC-Klasse berechnen oder ein anderes vergleichbares Toolkit von MFC erstellt haben, können Sie es in einer DLL platzieren.Diese DLL MFCxx.DLL verwendet, z. B., bleibt die endgültige Clientanwendung.Damit können wiederverwendbare Blatt, wiederverwendbare Klassen und Basisklassen wiederverwendbare Ansicht/Dokumentklassen.

Vor- und Nachteile

Warum sollte die gemeinsam genutzte MFC-Version verwenden?

  • Verwenden der gemeinsam genutzten Bibliothek kann kleinere Anwendungen führen (eine minimale Anwendung, die die meisten der MFC-Bibliothek ist kleiner als 10K).

  • Die gemeinsam genutzte MFC-Version unterstützt MFC-Erweiterungs-DLLs sowie eine reguläre DLL.

  • Eine Anwendung zu erstellen, die auf die freigegebenen MFC-Bibliotheken verwendet wird, ist schneller als eine statisch verknüpften MFC-Anwendung erstellen, da es nicht notwendig ist, MFC selbst verknüpft werden sollen.Dies ist in DEBUG Builds besonders, wenn der Linker die Debuginformationen komprimieren muss mit einer DLL mithilfe von Joins, die bereits die Debuginformationen enthält, gibt es weniger Debuginformationen in der Anwendung zu komprimieren.

Warum Sie die gemeinsam genutzte MFC-Version nicht verwendet werden sollten:

  • Das Versenden einer Anwendung, die die freigegebene Bibliothek verwendet, ist es erforderlich, dass Sie die Bibliothek MFCxx.DLL (und anderer) mit dem Programm veröffentlichen.MFCxx.DLL ist frei wie viele DLLs verteilbar. Sie müssen jedoch trotzdem die DLL im Setupprogramm installiert.Außerdem müssen Sie das MSVCRTxx.DLL versenden, das die C-RUNTIME-Bibliothek enthält, die vom Programm und die MFC-DLL selbst verwendet wird.

So erstellen Sie eine MFC-Erweiterungs-DLL schreibt

Eine MFC-Erweiterungs-DLL ist eine DLL, die die Klassen und Funktionen geschrieben werden, um die Funktionalität der MFC-Klassen zu verschönern enthält.Eine MFC-Erweiterungs-DLL verwendet die gemeinsam genutzten MFC-DLL, wie sie verwendet, unter denen eine Anwendung mit mehreren zusätzlichen Überlegungen:

  • Der Buildprozess ist mit dem Erstellen einer Anwendung, die die freigegebenen MFC-Bibliotheken für einige zusätzliche Compiler- und Linkeroptionen verwendet.

  • Eine MFC-Erweiterungs-DLL hat keinen CWinApp abgeleiteten Klasse.

  • Eine MFC-Erweiterungs-DLL spezielle muss DllMain bereitstellen.Anwendungs-Assistenten-Zubehör eine DllMain-Funktion, die Sie ändern können.

  • Eine MFC-Erweiterungs-DLL stellt normalerweise eine Initialisierungsroutine, um CDynLinkLibrary zu erstellen, wenn die Erweiterungs-DLL CRuntimeClass es oder Ressourcen in die Anwendung exportiert werden sollen.Eine abgeleitete Klasse CDynLinkLibrary kann verwendet werden, wenn Daten pro Anwendung von der Erweiterungs-DLL verwaltet werden müssen.

Diese Aspekte werden ausführlich im Folgenden beschrieben.Sie sollten auch die MFC wechselten zu verweisen, da es DLLHUSK Konzept Beispiel gezeigt:

  • Eine Anwendung mithilfe der gemeinsam genutzten Bibliotheken erstellen.(DLLHUSK.EXE ist eine MFC-Anwendung, die dynamisch an die MFC-Bibliotheken sowie zu anderen DLL) verknüpft.

  • Eine MFC-Erweiterungs-DLL erstellen.(Beachten Sie die speziellen Flags wie _AFXEXT, die verwendet werden, wenn eine Erweiterungs-DLL erstellt)

  • Zwei Beispiele für MFC-Erweiterungs-DLL.Man wird die grundlegende Struktur einer MFC-Erweiterungs-DLL mit eingeschränkten Exporten (TESTDLL1), und der andere Ausdruck ist das Exportieren einer gesamten Klassenschnittstelle (TESTDLL2).

müssen die Clientanwendung und einer beliebigen Erweiterungs-DLLs die gleiche Version von MFCxx.DLL verwenden.Sie sollten der Konvention folgen von MFC-DLLs sowie eine Debug- und Retail Version (/release) der Erweiterungs-DLL bereitstellen.Dies ermöglicht Clientanwendungen, die beide Versionen Retail zu erstellen und debuggen und verknüpfen sie ihre Anwendungen mit dem entsprechenden debug " oder " Retail Datenbankversion alle DLLs.

HinweisHinweis

Da C++-Namensergänzung und Export, der bei der Exporttarif aus einer Erweiterungs-DLL möglicherweise von den Debug- und Retail Versionen desselben DLL und DLLs für unterschiedliche Plattformen unterschiedlich sind.Der Einzelhandel MFCxx.DLL hat ca. 2000 exportierte Einstiegspunkte; MFCxxD.DLL Debuggen hat ca. 3000 exportierte Einstiegspunkte.

hw85e4bb.collapse_all(de-de,VS.110).gifSchneller Hinweis zur Speicherverwaltung

Der Abschnitt "Speicherverwaltung," in der Nähe des Endes des Hinweises technischen Titel wird, wird die Implementierung des MFCxx.DLL mit der gemeinsam genutzten MFC-Version.Die Informationen, die Sie kennen müssen, um eine Erweiterungs-DLL zu implementieren, werden im Folgenden beschrieben.

MFCxx.DLL und alle Erweiterungs-DLLs, die in den Adressbereich einer Clientanwendung geladen werden, verwenden dieselbe Speicherbelegungsfunktion, Ressourcen laden und andere "Global" Zustände MFC, als ob sie in derselben Anwendung waren.Dies ist wichtig, weil die MFC-fremde DLL-Bibliotheken und eine reguläre DLL, die statisch mit MFC verknüpft sind, die genaue und jedes von der DLL aufweist, das aus einem eigenen Speicherpool out zuordnet.

Wenn eine Erweiterungs-DLL Speicher belegt, kann dieser Arbeitsspeicher mit jedem anderen Objekt APPLICATION-zugeordneten vermischen.Auch wenn eine Anwendung, die die freigegebenen MFC-Bibliotheken verwendet, abstürzt, behält der Schutz des Betriebssystems die Integrität jeder anderen MFC-Anwendung, die die DLL freigibt.

Analog dazu werden andere "Global" MFC-Zustände, wie die aktuelle ausführbare Datei, aus der Ressourcen zu laden, auch zwischen der Clientanwendung und allen MFC-Erweiterungs-DLLs sowie MFCxx.DLL selbst aufgehoben.

hw85e4bb.collapse_all(de-de,VS.110).gifEine Erweiterungs-DLL erstellen

Mit Anwendungs-Assistenten verwenden, um ein MFC-Erweiterungs-DLL-Projekt zu erstellen, und es wird automatisch die entsprechenden Compiler- und Linkereinstellungen.Es war DllMain generiert außerdem eine Funktion, die Sie ändern können.

Wenn Sie ein vorhandenes Projekt in einer MFC-Erweiterungs-DLL konvertieren, beginnen Sie mit den Standardregeln zum Erstellen einer Anwendung mithilfe der gemeinsam genutzten MFC-Version, gehen Sie wie folgt vor:

  • Fügen Sie /D_AFXEXT-Flags für den Compiler hinzu.Klicken Sie im Dialogfeld Projekteigenschaften wählen Sie den Knoten C/C++ aus.Wählen Sie anschließend die Kategorie der Präprozessor aus.Fügen Sie dem _AFXEXT Feld definierens-Makro hinzu, und jedes Element durch ein Semikolon getrennt.

  • Entfernen Sie den /Gy Compilerschalter.Klicken Sie im Dialogfeld Projekteigenschaften wählen Sie den Knoten C/C++ aus.Wählen Sie anschließend die Kategorie der Codegenerierung aus.Stellen Sie sicher, dass "FUNCTION-LEVEL können Sie das" verknüpft ist, ist nicht aktiviert.Dies erleichtert die Klassen exportieren, da der Linker keine Funktionen ohne Verweis entfernt.Wenn für das ursprüngliche Projekt ein reguläres verwendete DLL zu erstellen, die statisch mit MFC verknüpft ist, ändern Sie die /MT[d]-Compileroption auf /MD[d].

  • Erstellen Sie eine Export Library mit der /DLL Option an LINK.Dadurch wird festgelegt, wenn Sie ein neues Ziel erstellen, und gibt Win32-Dynamic Link Library) als der Zieltyp an.

hw85e4bb.collapse_all(de-de,VS.110).gifIhre Headerdateien ändern

Das Ziel einer Erweiterungs-DLL handelt es sich normalerweise einige allgemeine Funktionalität in einer oder mehreren Anwendungen zu exportieren, die diese Funktionalität verwenden können.Dieses kocht unten zum Exportieren von Klassen und globale Funktionen, die für die Clientanwendungen zur Verfügung stehen.

Hierzu müssen Sie versichern dass jede der Memberfunktionen als Import oder Export entsprechend gekennzeichnet ist.Dies erfordert spezielle Deklarationen: __declspec(dllexport) und __declspec(dllimport).Wenn die Klassen von den Clientanwendungen verwendet werden, sollten Sie sie als __declspec(dllimport) deklariert werden.Wenn die Erweiterungs-DLL selbst erstellt wurde, sollten sie als __declspec(dllexport) deklariert werden.Darüber hinaus müssen die Funktionen, die tatsächlich exportiert werden, damit die Datenbindung Clientprogramm mit ihnen bei Ladezeit.

Um die gesamte Klasse exportieren, verwenden Sie AFX_EXT_CLASS in der Klassendefinition.Dieses Makro wird durch das Framework als __declspec(dllexport) definiert, wenn _AFXDLL und _AFXEXT definiert ist, definiert jedoch als __declspec(dllimport), wenn _AFXEXT nicht definiert ist._AFXEXT, wie oben beschrieben, wird nur definiert, wenn die Erweiterungs-DLL erstellt.Beispiele:

class AFX_EXT_CLASS CExampleExport : public CObject
{ ... class definition ... };

hw85e4bb.collapse_all(de-de,VS.110).gifKein Exportieren der gesamten Klasse

Möglicherweise möchten Sie nur die einzigen erforderlichen Member der Klasse exportieren.Möglicherweise benötigen Sie beim Exportieren einer von CDialog abgeleiteten Klasse z. B. nur den Konstruktor und den DoModal-Aufruf.Sie können diese Member zu exportieren, die die DEF-Datei der DLL verwenden, aber Sie können auch auf den individuellen AFX_EXT_CLASS Mitgliedern auf ähnliche Weise verwenden, die Sie exportieren möchten.

Beispiele:

class CExampleDialog : public CDialog
{
public:
   AFX_EXT_CLASS CExampleDialog();
   AFX_EXT_CLASS int DoModal();
   // rest of class definition
   .
   .
   .
};

Dabei werden möglicherweise in ein zusätzliches Problem ausgeführt, da Sie nicht mehr alle Member der Klasse exportieren.Das Problem liegt an der Art, die MFC-Makros bearbeiten.Es gibt derzeit verschiedene MFC-Hilfsmakros, durch die Datenmember deklariert oder definiert werden.Daher müssen diese Datenmember auch aus der DLL exportiert werden.

Das DECLARE_DYNAMIC-Makro wird beim Erstellen einer Erweiterungs-DLL z. B. 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 "statisches AFX_DATA" beginnt, deklariert ein statisches Objekt innerhalb der Klasse.Um diese Klasse ordnungsgemäß zu exportieren und die Laufzeitinformationen von einem Client .EXE zuzugreifen, müssen Sie diese statische Objekt exportieren.Da das statische Objekt mit dem AFX_DATA-Modifizierer deklariert wird, müssen Sie AFX_DATA beim Erstellen der DLL einfach als __declspec(dllexport) und beim Erstellen des ausführbaren Clients als __declspec(dllimport) definieren.

Wie oben erläutert wird AFX_EXT_CLASS bereits auf diese Weise definiert.Sie müssen lediglich AFX_DATA neu definieren, um mit AFX_EXT_CLASS um die Klassendefinition sein.

Beispiele:

   #undef  AFX_DATA
   #define AFX_DATA AFX_EXT_CLASS
   class CExampleView : public CView
   {
     DECLARE_DYNAMIC()
     // ... class definition ...
   };
   #undef  AFX_DATA
   #define AFX_DATA

MFC verwendet immer das AFX_DATA Symbol für Datenelemente, die innerhalb der Makros definiert, sodass dieser Technik funktioniert für all diese Szenarien.Zum Beispiel funktioniert sie für DECLARE_MESSAGE_MAP.

HinweisHinweis

Wenn Sie anstelle ausgewählter Klassenmember die gesamte Klasse exportieren, werden statische Datenmember automatisch exportiert.

Sie können das gleiche Verfahren verwenden, um den CArchive-Operator für Klassen Extraktions automatisch zu exportieren, die die DECLARE_SERIAL und IMPLEMENT_SERIAL Macros.Exportieren Sie den Operator " Archiv mit den Klassendeklarationen in (markieren. .h-Datei) mit folgendem Code:

#undef AFX_API
#define AFX_API AFX_EXT_CLASS

<your class declarations here>

#undef AFX_API
#define AFX_API

hw85e4bb.collapse_all(de-de,VS.110).gifEinschränkungen von _AFXEXT

Sie können das _AFXEXT Präprozessorsymbol für die Erweiterungs-DLL verwenden, solange Sie nicht mehrere Ebenen Erweiterungs-DLL haben.Wenn Sie über Erweiterungs-DLLs verfügen, die Klassen in Ihren eigenen Erweiterungs-DLLs aufrufen oder von darin enthaltenen Klassen ableiten und diese DLLs wiederum von MFC-Klassen abgeleitet werden, müssen Sie ein eigenes Präprozessorsymbol verwenden, um Mehrdeutigkeiten zu vermeiden.

Bei Win32 besteht das Problem darin, dass Sie alle Daten explizit als __declspec(dllexport) deklarieren müssen, wenn sie aus einer DLL exportiert werden sollen, und als __declspec(dllimport), wenn sie aus einer DLL importiert werden sollen.Wenn Sie _AFXEXT definieren, wird durch die MFC-Header sichergestellt, dass AFX_EXT_CLASS korrekt definiert wird.

Wenn Sie mehrere Ebenen ist ein Symbol, das AFX_EXT_CLASS nicht ausreichend, da eine Erweiterungs-DLL möglicherweise neue Klassen exportieren sowie andere Klassen von einer anderen Erweiterungs-DLL importieren.Um dieses Problem zu behandeln, verwenden Sie ein spezielles Präprozessorsymbol, das angibt, dass Sie die DLL selbst anhand der Anwendung der DLL erstellen.Angenommen, zwei Erweiterungs-DLL A.DLL und B.DLL vor.Exportieren einer Sie einige Klassen in A.H und B.H.B.DLL verwendet die Klassen von A.DLL.Die Headerdateien würden in etwa wie folgt aussehen:

/* A.H */
#ifdef A_IMPL
   #define CLASS_DECL_A   __declspec(dllexport)
#else
   #define CLASS_DECL_A   __declspec(dllimport)
#endif

class CLASS_DECL_A CExampleA : public CObject
{ ... class definition ... };

/* B.H */
#ifdef B_IMPL
   #define CLASS_DECL_B   __declspec(dllexport)
#else
   #define CLASS_DECL_B   __declspec(dllimport)
#endif

class CLASS_DECL_B CExampleB : public CExampleA
{ ... class definition .. };

Wenn A.DLL erstellt wird, wird es mit /D A_IMPL erstellt und B.DLL erstellt wird, wird es mit /D B_IMPL erstellt.Indem separate Symbole für jedes DLL verwendet, wird CExampleB exportiert und importiert wird CExampleA beim Erstellen B.DLL erstellt.CExampleA exportiert wird, sofern A.DLL importiert und erstellt, wenn diese durch B.DLL verwendet wird (oder einen anderen Client).

Dieser Typ der Überlagerung kann nicht durchgeführt werden, wenn er integrierte AFX_EXT_CLASS und die _AFXEXT Präprozessorsymbole verwendet.Die Technik, die oben beschriebene löst dieses Problem ähnlich den Mechanismus nicht anders verwendet MFC selbst bei der Datenbank-, OLE- und Netzwerk erweiterungs-dll zu erstellen.

hw85e4bb.collapse_all(de-de,VS.110).gifKein Exportieren der gesamten Klasse

Auch müssen Sie besondere Sorgfalt verwenden, wenn Sie keine gesamte Klasse exportieren.Sie müssen sicherstellen, dass die erforderlichen Datenelemente, die durch die MFC-Makros erstellten ordnungsgemäß exportiert werden.Dies kann erfolgen, indem der Makro AFX_DATA dem bestimmten Klasse neu definiert.Die Neudefinition ist jedes Mal erforderlich, wenn Sie nicht die gesamte Klasse exportieren.

Beispiele:

// A.H
#ifdef A_IMPL
   #define CLASS_DECL_A  _declspec(dllexport)
#else
   #define CLASS_DECL_A  _declspec(dllimport)
   #endif

#undef  AFX_DATA
#define AFX_DATA CLASS_DECL_A

class CExampleA : public CObject
{
   DECLARE_DYNAMIC()
   CLASS_DECL_A int SomeFunction();
   //class definition 
   .
   .
   .
};

#undef AFX_DATA
#define AFX_DATA

hw85e4bb.collapse_all(de-de,VS.110).gifDllMain

Im Folgenden wird der vollständige Code, den Sie in der Hauptquelldatei für die Erweiterungs-DLL legen sollen.Es sollte stammen, nachdem der Standardeinstellung enthält.Wenn Sie Anwendungs-Assistenten verwenden, um Startdateien für eine Erweiterungs-DLL zu erstellen, stellt sie DllMain für Sie.

#include "afxdllx.h"

static AFX_EXTENSION_MODULE extensionDLL;

extern "C" int APIENTRY 
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
{
   if (dwReason == DLL_PROCESS_ATTACH)
   {
      // Extension DLL one-time initialization 
      if (!AfxInitExtensionModule(
             extensionDLL, hInstance))
         return 0;

      // TODO: perform other initialization tasks here
   }
   else if (dwReason == DLL_PROCESS_DETACH)
   {
      // Extension DLL per-process termination
      AfxTermExtensionModule(extensionDLL);

          // TODO: perform other cleanup tasks here
   }
   return 1;   // ok
}

Der Aufruf von AfxInitExtensionModule zeichnet die Module RUNTIME Klassen (CRuntimeClass-Strukturen) sowie seine Objekt factorys (COleObjectFactory-Objekte) für die Verwendung später auf, wenn das CDynLinkLibrary-Objekt erstellt wird.Die (optionale) Aufruf von AfxTermExtensionModule kann MFC verwendet, um die Erweiterungs-DLL zu bereinigen, wobei jeder Prozess (der Fall, wenn der Prozess beendet wird, oder wenn die DLL aufgrund eines FreeLibrary Aufrufs entladen wird) von der Erweiterungs-DLL getrennt werden.Da die meisten Erweiterungs-DLL nicht dynamisch (normalerweise, werden sie über das Importbibliotheken verknüpft) geladen wird, ist der Aufruf von AfxTermExtensionModule i. d. R. nicht erforderlich.

Wenn die Anwendung Erweiterungs-DLL dynamisch lädt und freigibt, müssen Sie AfxTermExtensionModule Aufruf wie weiter oben.Stellen Sie außerdem sicher, AfxLoadLibrary und AfxFreeLibrary zu verwenden (und nicht funktioniert LoadLibrary Win32- und FreeLibrary), wenn die Anwendung mehrere Threads verwendet oder wenn sie eine Erweiterungs-DLL dynamisch lädt.Verwenden AfxLoadLibrary und AfxFreeLibrary versichert Starten und Herunterfahren, dass der Code, der ausgeführt wird, wenn die Erweiterungs-DLL geladen und entladen wird, den globalen MFC-Zustand nicht beschädigt.

Die Headerdatei AFXDLLX.H enthält spezielle Definitionen für die Strukturen, die in der Erweiterungs-DLL, wie der Definition für AFX_EXTENSION_MODULE und CDynLinkLibrary verwendet werden.

Das globale wie dargestellt extensionDLL muss deklariert werden.Im Gegensatz zur 16-Bit-Version von MFC können Sie MFC-Funktionen während dieser Zeit Speicher belegen und aufrufen, da das MFCxx.DLL vollständig initialisiert wurde, bis das DllMain aufgerufen wird.

hw85e4bb.collapse_all(de-de,VS.110).gifGemeinsame Nutzung von Ressourcen und Klassen

Einfacher nur einige der Export mit niedriger Bandbreite MFC-Erweiterungs-DLL-Anforderung Funktionen zur Clientanwendung und keine Daten mehr.Mehr Benutzeroberfläche intensives DLL sollte Ressourcen und C++-Klassen in der Clientanwendung exportieren.

Der Export von Ressourcen erfolgt über eine Ressourcenliste.In jeder Anwendung ist eine einfach verknüpften Liste von CDynLinkLibrary-Objekten.Wenn sie nach einer Ressource durchsuchen, sollten die meisten Implementierungen des Standardwerts MFC, die Ressourcen laden, zuerst das aktuelle Modul Ressourcen (AfxGetResourceHandle) und die Liste der derzeit nicht gefunden CDynLinkLibrary-Objekten, die die angeforderte Ressource zu laden.

Dynamische Build angegebenen Klassennamen Ein C++-Compiler C++-Objekte ist ähnlich.Der Mechanismus für deserialisierungs MFC-Objekt CRuntimeClass muss alle Objekte verfügen, die registriert werden, damit er erneut erstellen kann, indem er dynamisch C++-Objekt des erforderlichen Typs erstellt anhand der zuvor gespeichert wurde.

Wenn Sie möchten, dass die Clientanwendung Klassen in der Erweiterungs-DLL zu verwenden, die DECLARE_SERIAL sind, müssen Sie die Klassen exportieren, um die Clientanwendung angezeigt werden soll.Dies ist auch hierzu die CDynLinkLibrary Liste durchläuft.

Im Fall von MFC erweiterte Konzept der Liste, DLLHUSK Beispiel sieht in etwa:

head ->   DLLHUSK.EXE   - or -   DLLHUSK.EXE
               |                      |
          TESTDLL2.DLL           TESTDLL2.DLL
               |                      |
          TESTDLL1.DLL           TESTDLL1.DLL
               |                      |
               |                      |
            MFC90D.DLL            MFC90.DLL

Das MFCxx.DLL ist in der Regel zuletzt in der Liste Ressourcen- und Klassen.MFCxx.DLL schließt alle MFC-Standardressourcen, einschließlich Eingabeaufforderungs-Zeichenfolgen für die gesamte standardmäßige ID Befehl ein.Das Platzieren es am Ende der Liste können DLLs und die Clientanwendung selbst eine eigene Kopie der MFC-Standardressourcen, jedoch nicht auf die im gemeinsam genutzten Ressourcen stattdessen MFCxx.DLL zu verlassen.

Das Zusammenführen von Ressourcen und Klassennamen alle DLLs in den Namespace der Clientanwendung hat den Nachteil, müssen Sie darauf achten, dass die Namen oder IDs werden.Sie können diese Funktion deaktivieren, indem Sie natürlich nicht die Ressourcen oder ein CDynLinkLibrary-Objekt an die Clientanwendung exportieren.Im DLLHUSK-Beispiel wird der Namespace für gemeinsam genutzte Ressourcen mithilfe mehrerer Headerdateien verwaltet.Weitere Informationen finden Sie unter Technischer Hinweis 35 für Tipps zur Verwendung von Dateien der freigegebenen Ressource.

hw85e4bb.collapse_all(de-de,VS.110).gifDie DLL initialisieren

Wie bereits erwähnt, werden Sie gewöhnlich einen CDynLinkLibrary-Objekt erstellen, um die Ressourcen und Klassen in der Clientanwendung zu exportieren.Sie müssen einen exportierten Einstiegspunkt angeben, um die DLL zu initialisieren.Minimal ist dies eine ungültige Routine, die keine Argumente akzeptiert und nichts zurückgibt, kann jedoch vergewissern, dass alles.

Jede Clientanwendung, die die DLL verwenden möchte, muss diese Initialisierungsroutine aufrufen, wenn Sie diesen Ansatz verwenden.Ordnen Sie können auch dieses CDynLinkLibrary-Objekt im DllMain gleich nach dem Aufrufen von AfxInitExtensionModule.

Die Initialisierungsroutine muss ein CDynLinkLibrary-Objekt im aktuellen Heap der Anwendung erstellen, der bis zu den Erweiterungs-DLL-Informationen verkabelt ist.Dies kann mit dem folgenden Schritte ausgeführt werden:

extern "C" extern void WINAPI InitXxxDLL()
{
   new CDynLinkLibrary(extensionDLL);
}

Der Name der Routine, InitXxxDLL in diesem Beispiel kann aller sein, den Sie verwenden möchten.Er muss nicht extern "C" sein, aber diese macht so den Exporttarif einfacher zu warten.

HinweisHinweis

Wenn Sie die Erweiterungs-DLL aus einer regulären DLL verwenden, müssen Sie diese Initialisierungsfunktion exportieren.Vor der Verwendung von Erweiterungs-DLL-Klassen oder - Ressourcen diese Funktion muss von der regulären DLL aufgerufen werden.

hw85e4bb.collapse_all(de-de,VS.110).gifEinträge exportieren

Die einfache Möglichkeit, Ihre Klassen exportieren, ist __declspec(dllimport) und __declspec(dllexport) für jede Klasse und globale Funktion zu verwenden, die Sie exportieren möchten.Dadurch ist es viel einfacher, ist aber weniger effizient als jeden Einstiegspunkt benennend (unten beschrieben), da Sie verfügen über weniger Steuerelement, welche Funktionen exportiert werden, und Sie die Funktionen nicht von Ordnungszahl exportiert werden können.TESTDLL1 und TESTDLL2 verwenden diese Methode, um die Einträge zu exportieren.

Eine effizientere Methode (und die Methode von MFCxx.DLL) ist, jeden Eintrag manuell zu exportieren, indem Sie jeden Eintrag in der DEF-Datei benennen.Da wir die selektive Exporte aus unserem DLL (d. h. nicht alle) exportieren, müssen Sie sich entscheiden, die bestimmte Schnittstellen Sie exportieren möchten.Dies ist schwierig, da Sie die ergänzten Namen für den Linker in Form von Einträgen in der DEF-Datei angeben müssen.Exportieren Sie keine C++-Klassen, es sei denn, Sie tatsächlich einen symbolischen Links für sie benötigen.

Wenn Sie versucht haben, C++-Klassen mit einer DEF-Datei vor zu exportieren, müssen Sie ein Tool entwickeln, um diese Liste automatisch zu generieren.Dies kann mithilfe eines zweistufigen Verbindungsprozesses erfolgen.Verknüpfen Sie die DLL einmal ohne und Exporte können Sie den Linker, um eine .MAP-Datei zu generieren.Die .MAP-Datei kann verwendet werden, um eine Liste von Funktionen zu generieren, die exportiert werden sollen, sodass einige Neuanordnung, kann sie verwendet werden, um die EXPORT-Einträge für Ihre DEF-Datei zu generieren.Der Exporttarif für MFCxx.DLL und OLE erweiterungs-dll und die Datenbank mehrere tausend zahlreich, wurde mit einem solchen Vorgang generiert (obwohl dies nicht automatisch abgeschlossen ist und alle Hand benötigt, die von Zeit zu Zeit optimieren).

hw85e4bb.collapse_all(de-de,VS.110).gifCWinApp mit einer Gegensignatur.CDynLinkLibrary

Eine MFC-Erweiterungs-DLL hat keinen CWinApp eigene abgeleitete Objekt. Stattdessen muss sie mit CWinApp funktionieren abgeleiteten Objekts der Clientanwendung.Dies bedeutet, dass die Clientanwendung die Haupt-Meldungsverteilschleife besitzt, die Ruheschleife usw.

Wenn die MFC-Erweiterungs-DLL zusätzliche Daten für jede Anwendung warten muss, können Sie eine neue Klasse von CDynLinkLibrary ableiten und in der InitXxxDLL-Routine Sie oben beschrieben zu erstellen.Die DLL kann dann bei ihrer Ausführung die Liste der CDynLinkLibrary-Objekte der aktuellen Anwendung überprüfen, um das Objekt für die jeweilige Erweiterungs-DLL zu suchen.

hw85e4bb.collapse_all(de-de,VS.110).gifVerwenden von Ressourcen in der DLL-Implementierung

Wie bereits erwähnt, ist die Standardeinstellung CDynLinkLibrary Laden von Ressourcen die Liste der Objekte, die zum ersten EXE oder DLL nach dem stellen die angeforderte Ressource verfügt.Alle MFC API sowie aller internen Code verwendet AfxFindResourceHandle Liste durchlaufen, um die Ressourcen jede Ressource zu suchen, unabhängig davon, wo sie sich befindet.

Wenn Sie Ressourcen aus nur einer bestimmten Stelle laden möchten, verwenden Sie die APIs AfxGetResourceHandle und AfxSetResourceHandle, um das alte Handle zu speichern und das neue Handle festzulegen.Achten Sie darauf, dass Sie das alte Ressourcenhandle wiederherstellen, bevor Sie zur Clientanwendung zurückkehren.Das Beispiel TESTDLL2 verwendet diesen Ansatz für ein Menü explizit laden.

Das Durchlaufen der Liste hat jedoch den Nachteil, dass die Suche etwas langsamer ist und dass die Ressourcen-ID-Bereiche verwaltet werden müssen.Der Vorteil liegt darin, dass eine Clientanwendung, die mit mehreren Erweiterungs-DLLs verknüpft ist, jede durch die DLL zur Verfügung gestellte Ressource nutzen kann, ohne dass das DLL-Instanzenhandle angegeben werden muss.AfxFindResourceHandle ist eine API, die bei der Suche nach einer bestimmten Übereinstimmung die Ressourcenliste durchläuft.Sie verwendet den Ressourcennamen und -typ als Parameter und gibt das zuerst ermittelte Ressourcenhandle (oder NULL) zurück.

Eine Anwendung schreiben, die die DLL-Version verwendet

hw85e4bb.collapse_all(de-de,VS.110).gifAnwendungs-Anforderungen

Eine Anwendung, die die gemeinsam genutzte MFC-Version verwendet, muss einigen einfachen Regeln einhalten:

  • Sie muss ein CWinApp-Objekt den Standardregeln für eine Meldungsverteilschleife folgen.

  • Sie muss mit einem Satz von erforderlichen Flags für Compiler kompiliert werden (siehe unten).

  • Sie müssen mit den MFCxx-Importbibliotheken verknüpfen.Indem Sie die erforderlichen Compiler Flags festlegen, bestimmen die MFC-Header, der zur Verknüpfungszeit Bibliothek die Anwendung verknüpft werden soll.

  • Um die ausführbare Datei ausführen möchten, muss in dem Pfad MFCxx.DLL oder im Windows-Systemverzeichnis.

hw85e4bb.collapse_all(de-de,VS.110).gifErstellen mit der Entwicklungsumgebung

Wenn Sie die interne Makefile mit den meisten Standard festgelegten verwenden, können Sie das Projekt problemlos ändern, die DLL-Version zu erstellen.

Der nächste Schritt wird davon ausgegangen, dass Sie über eine funktionsfähige MFC-Anwendung fehlerfrei verfügen, die mit NAFXCWD.LIB (Debuggen) und NAFXCW.LIB (für Einzelhandel) und Sie möchten diesen konvertieren, um die freigegebene Version der MFC-Bibliothek zu verwenden.Führen Sie die Visual C++-Umgebung und haben eine interne Projektdatei.

  1. Zeigen Sie im Menü ProjekteEigenschaften.In der Allgemein Seite mit Projektstandards, legen Sie fest MFC in einer gemeinsam genutzten DLL verwenden zu Microsoft Foundation Classes (D) MFCxx (.dll).

hw85e4bb.collapse_all(de-de,VS.110).gifErstellen mit NMAKE

Wenn Sie die Funktion von Visual C++ externes Makefile verwenden oder NMAKE direkt verwenden, müssen Sie Ihre Makefiles bearbeiten, um Compiler- und Linkeroptionen unterstützen

Erforderliche Compiler Flags:

  • /D_AFXDLL /MD
    /D_AFXDLL

Die Header des Standardwerts MFC benötigen dieses Symbol definiert wird:

  • /MD
    Die Anwendung muss die DLL-Version der C-Laufzeitbibliothek verwenden

Alle anderen Compiler Flags folgen den MFC-Standards (z. B. _DEBUG für Debuggen).

Bearbeiten Sie die Liste der Bibliotheken Linker.Ändern Sie NAFXCWD.LIB zu MFCxxD.LIB, und ändern Sie NAFXCW.LIB zu MFCxx.LIB.Ersetzen Sie LIBC.LIB von MSVCRT.LIB.Wie bei jeder anderen MFC-Bibliothek ist es wichtig, dass MFCxxD.LIB platziertes before alle C-RUNTIME-Bibliotheken ist.

Optional Einzelhandel Fügen Sie dem /D_AFXDLL hinzu und debuggen Sie Optionen für den Ressourcencompiler (die tatsächlich die Ressourcen mit /R kompiliert).Dies macht das abschließende ausführbares kleineres, indem die Ressourcen, die in den MFC-DLLs vorhanden sind.

Ein vollständiges Neuerstellung wird benötigt, nachdem diese Änderungen vorgenommen wurden.

hw85e4bb.collapse_all(de-de,VS.110).gifDie Beispiele erstellen

Die meisten MFC-Beispielprogramme können vom Visual C++ oder einer freigegebenen NMAKE-kompatiblen MAKEFILE über die Befehlszeile erstellt werden.

Um diese Beispiele zu konvertieren, um MFCxx.DLL zu verwenden, können Sie die .MAK-Datei in Visual C++ laden und die Projektoptionen festlegen wie oben beschrieben.Wenn Sie die NMAKE-Erstellung verwenden, können Sie "AFXDLL=1" auf der NMAKE-Befehlszeile angeben und erstellt das Beispiel mithilfe der freigegebenen MFC-Bibliotheken.

Das MFC erweiterte Konzepte Beispiel DLLHUSK mit der DLL-Version von MFC erstellt wird.Dieses Beispiel wird nicht nur, wie eine Anwendung erstellt wird, die MFCxx.DLL verknüpft ist, sondern es wird auch andere Features der Option MFC-DLL-Verpackungs wie MFC-Erweiterungs-DLL, die später in diesem technischen Hinweis beschrieben wird.

hw85e4bb.collapse_all(de-de,VS.110).gifVerpackungs-Hinweise

Die Version der DLL Retail MFCxx (.DLL) [U] verteilbar gemeinsam sind.Die Debugversion der DLL kann nicht gemeinsam verteilbar und sollten nur während der Entwicklung der Anwendung verwendet werden.

Das Debuggen von DLLs wird mit Debuginformationen zu gewährleisten.Mit dem Visual C++-Debugger können Sie die Ausführung der Anwendung und DLL aufzeichnen.Die Version der DLL MFCxx (.DLL] [E) enthalten keine Debuginformationen.

Wenn Sie die DLL neu erstellen oder anpassen, sollten Sie sie etwas anders MFCxx "," bezeichnet wird, das die Datei MFCDLL.MAK MFC SRC Buildoptionen beschreibt und die Logik zum Benennen der DLL enthält.Die Dateien umbenennen ist erforderlich, da diese DLL von vielen MFC-Anwendungen möglicherweise freigegeben ist.Die benutzerdefinierte Version der MFC-DLL seien ihre, ersetzen Sie die auf dem System installiert sind, kann eine andere MFC-Anwendung mithilfe der gemeinsam genutzten MFC-DLL unterbrechen.

Das Erstellen der MFC-DLL wird nicht empfohlen.

Wie das MFCxx.DLL implementiert wird

Im folgenden Abschnitt wird beschrieben, wie die MFC-DLL (MFCxx.DLL und MFCxxD.DLL) implementiert wird.Verstehend sind die Informationen hier außerdem nicht wichtig, wenn alle Sie möchten die MFC-DLL mit der Anwendung zu verwenden ist.Die Details können hier keine Voraussetzung zum Verständnis, wie eine MFC-Erweiterungs-DLL schreibt, aber das Verständnis dieser Implementierung möglicherweise erleichtert Ihnen dabei, Ihre eigenen DLL zu schreiben.

hw85e4bb.collapse_all(de-de,VS.110).gifImplementierungs-Übersicht

Die MFC-DLL ist eine besondere Variante einer MFC-Erweiterungs-DLL, wie oben beschrieben.Sie haben eine sehr große Anzahl von Exporten für viele Klassen.Es gibt einige zusätzliche Schritte, die wir in der MFC-DLL selbst verfügbar machen, von denen sie als eine normale Erweiterungs-DLL verwenden.

hw85e4bb.collapse_all(de-de,VS.110).gifWin32 Großteil der Arbeit, die erledigt

Die 16-Bit-Version von MFC erfordern einige spezielle Techniken z. B. Pro App Daten auf dem Stapel segment, den speziellen Segmenten, die von Assemblycode entweder 80x86 erstellt wurden, den Ausnahme kontexten pro Prozess und andere Techniken.Win32 unterstützt pro Prozess Daten direkt in einer DLL, das, was Sie der Regel soll.In den meisten Fällen handelt es sich einfach MFCxx.DLL NAFXCW.LIB, die in eine DLL gepackt wird.Wenn Sie den MFC-Quellcode berücksichtigen, suchen Sie sehr wenig #ifdef _AFXDLL, da es sehr wenige besondere Fälle gibt, die vorgenommen werden müssen.In besonderen Fällen sind die dort speziell für Windows 3.1 Win32 zu verarbeiten (Win32) bezeichnet als andere.DLL-Daten Win32 unterstützt keine direkte pro Prozess. Daher muss die MFC-DLL den lokalen Threadspeicher (TLS) Win32-API verwenden, um lokale ProzeßBezugspunkte.

hw85e4bb.collapse_all(de-de,VS.110).gifAuswirkungen auf Bibliotheks-Quellen, zusätzliche Dateien

Die Auswirkungen der _AFXDLL-Version auf den normalen MFC-Klassen-Bibliotheks quellen und Headern sind relativ klein.Es gibt eine spezielle versions Datei (AFXV_DLL.H) sowie eine zusätzliche AFXDLL_.H Headerdatei () durch den Header der main AFXWIN.H.Der AFXDLL_.H-Header schließt die CDynLinkLibrary-Klasse und andere Implementierungsdetails von _AFXDLL-Anwendungen und FROM MFC-Erweiterungs-DLL ein.Der AFXDLLX.H-Header wird zum Erstellen einer MFC-Erweiterungs-DLL bereitgestellt werden (siehe oben). Weitere Einzelheiten

Die regulären Quellen mit der MFC-Bibliothek in MFC SRC zusätzlicher haben bedingungscode unter dem _AFXDLL #ifdef.Eine zusätzliche Quelldatei (DLLINIT.CPP) enthält den Initialisierungscode der zusätzliche DLL und anderen Kleber für die gemeinsam genutzte MFC-Version.

Um die gemeinsam genutzte MFC-Version erstellt wird, werden zusätzliche Dateien bereitgestellt.(Siehe unten für Details dazu, wie die DLL erstellt.)

  • Zwei DEF-Dateien werden zum Exportieren der MFC-DLL-Einstiegspunkte für MFCxxD.DEF (Debug) und Versionen (MFCxx.DEF) der DLL gemeinsam verwenden.

  • Eine RC-Datei (MFCDLL.RC) enthält alle MFC-Standardressourcen und eine VERSIONINFO-Ressource für die DLL.

  • Eine .CLW-Datei (MFCDLL.CLW) wird bereitgestellt, um das Durchsuchen der MFC-Klassen mit ClassWizard zu ermöglichen.Hinweis: Diese Funktion ist nicht auf die DLL-Version von MFC bestimmt.

hw85e4bb.collapse_all(de-de,VS.110).gifSpeicherverwaltung

Eine Anwendung, die MFCxx.DLL verwendet eine allgemeine Speicherbelegungsfunktion, die von MSVCRTxx.DLL, das freigegebene C-RUNTIME DLL bereitgestellt wird.Die Anwendung einer Erweiterungs-DLL und wie gut der MFC-DLL selbst verwenden diese freigegebene Speicherbelegungsfunktion.Mit einer gemeinsam genutzten DLLs für Speicherbelegung verwenden, können die MFC-DLL Speicher belegen, die später von der Anwendung oder umgekehrt freigegeben wird.Da die Anwendung und DLL dieselbe Belegungsfunktion verwenden müssen, sollten Sie operator new globales C++ oder operator delete nicht überschreiben.Die gleichen Regeln gelten für den Rest der C-Laufzeit-Speicherbelegungs routinen (z. B. malloc, realloc, free und andere).

hw85e4bb.collapse_all(de-de,VS.110).gifOrdnungszahlen und - Klasse __declspec (dllexport) und DLL-Benennung

Wir verwenden nicht die Funktionalität class**__declspec(dllexport)** des C++-Compilers.Stattdessen wird eine Liste von Exporten mit den MFCxx.DEF quellen Klassenbibliothek enthalten (und MFCxxD.DEF).Nur die Option werden diese Funktionen und Daten (Einstiegspunkte festgelegt) exportiert.Anderen Symbolen, z. B. private Implementierungen von MFC - Klassen oder Funktionen werden nicht alle Exporte sind nach Ordnungszahl ohne hierzu einen Zeichenfolgennamen in Bewohner ansässigen oder nicht in der Namenstabelle exportiert.

Verwenden class ist __declspec(dllexport) durchführbare Alternative zum Erstellen einer kleineren DLL, sondern im Falle eines großen DLL wie MFC verfügt der standardmäßigen exportierende Mechanismus Leistungsfähigkeits- Kapazität und trennen.

Was dies alles bedeutet, dass wir große Mengen an ein Paket Funktionalität in der Version MFCxx.DLL können, die nur ungefähr 800 KB groß ist, ohne die Ausführung zu beeinträchtigen oder Geschwindigkeit zu laden.MFCxx.DLL würde 100K war diese Technik nicht mehr verwendet worden sein.Dadurch ist es auch möglich, zusätzliche Einstiegspunkte am Ende der DEF-Datei hinzugefügt werden, um einfache Versionsverwaltung zu ermöglichen, ohne die Geschwindigkeits- und Exportierens von Größen-Leistungsfähigkeit zu gefährden nach Ordnungszahl.Hauptversionsrevisionen in der MFC-Klassen-Bibliothek ändern den Bibliotheksnamen.Das heißt, MFC30.DLL das verteilbare DLL, die Version 3.0 der MFC-Klassen-Bibliothek enthält.Upgrade diese DLL in einem hypothetischen sich sagen, die DLL MFC 3.1 MFC31.DLL würde stattdessen benannt.Auch wenn Sie den MFC-Quellcode ändern, um eine benutzerdefinierte Version der MFC-DLL zu erstellen, verwenden Sie einen anderen Namen (vorzugsweise einen ohne MFC "und" im Namen).

Siehe auch

Weitere Ressourcen

Technische Hinweise durch Zahl

Technische Hinweise nach Kategorie