TN011 : À l'aide de MFC dans le cadre d'une DLL
Cette remarque décrit les DLL normales, qui vous permettent d'utiliser la bibliothèque MFC dans une bibliothèque de liens dynamiques (DLL) windows.Il suppose que vous êtes familiarisé avec les DLL windows et comment les générer.Pour plus d'informations sur MFC les DLL d'extension, avec lesquels vous pouvez créer des extensions à la bibliothèque MFC, consultez Version DLL de MFC.
Interfaces DLL
Les DLL normales liées de manière supposent que les interfaces entre l'application et la DLL sont spécifiées dans les fonctions comme un C ou des classes explicitement exportées.Les interfaces de classe MFC ne peuvent pas être exportées.
Si une DLL et une application veut utiliser MFC, faites lier un tableau à utiliser la version partagée des bibliothèques MFC ou à statiquement à une copie des bibliothèques.L'application et la DLL peuvent les deux utiliser l'une des versions standard de la bibliothèque MFC.
Les DLL normales liées de manière ont plusieurs avantages :
L'application utilisant la DLL ne doit pas utiliser MFC et ne doit pas être une application Visual C++.
Avec les DLL normales liées de manière statique aux MFC, la taille de la DLL dépend uniquement MFC et d'un package de runtime C utilisés et liés.
Avec les DLL normales liées de manière dynamique aux MFC, l'enregistre dans la mémoire d'utiliser la version partagée des MFC peut être significatif.Toutefois, vous devez distribuer les DLL, le cpc<version>.dll et le Msvvcrt partagés<version>.dll, avec la DLL.
La création de DLL est indépendant de la façon dont les classes sont implémentées.Votre conception de DLL exporte uniquement aux API que vous souhaitez.Par conséquent, si l'implémentation change, les DLL normales sont encore valides.
Avec les DLL normales liées de manière statique aux MFC, si la DLL et l'application utilisent MFC, il n'y a aucun problème avec l'application qui souhaite une autre version MFC que la DLL ou vice versa.Étant donné que la bibliothèque MFC est liée dans chaque DLL ou EXE, il n'y a aucune question à propos de la version vous avez.
Limitations d'API
Certaines fonctionnalités MFC ne s'applique pas à la version DLL, ou en raison de les limitations techniques ou parce que ces services sont généralement fournis par l'application.Avec la version actuelle de MFC, la seule fonction qui n'est pas applicable est CWinApp::SetDialogBkColor.
Générer votre DLL
Lors de la compilation les DLL normales liées de manière statique aux MFC, les symboles _USRDLL et _WINDLL doit être défini.Votre code de la DLL doit également être compilé avec des commutateurs de compilation suivants :
/D_WINDLL signifie la compilation est pour une DLL
/D_USRDLL spécifiez génèrent une DLL normale
Vous devez également définir ces symboles et utiliser ces commutateurs de compilation lorsque vous compilez les DLL normales liées de manière dynamique aux MFC.En outre, le symbole _AFXDLL doit être défini et votre code de la DLL doit être compilé avec :
- /D_AFXDLL spécifie que vous vouliez générer une DLL normale liée de manière dynamique aux MFC
Les interfaces API () entre l'application et la DLL doivent être explicitement exportées.Nous vous conseillons de définir vos interfaces pour être bande passante restreinte, et utilisons uniquement des interfaces C si possible.Il est plus facile à maintenir les interfaces directes C que les classes plus complexes C++.
Placez les API dans un en-tête séparé qui peut être inclus dans les fichiers C et C++.Consultez l'en-tête ScreenCap.h dans l'exemple DLLScreenCap de concepts avancés par MFC pour obtenir un exemple.Pour exporter les fonctions, écrivez-les dans la section d' EXPORTS de votre fichier de définition de module (.DEF) ou incluez __declspec(dllexport) sur vos définitions de fonction.Utilisez __declspec(dllimport) pour importer ces fonctions dans l'exécutable client.
Vous devez ajouter la macro d' AFX_MANAGE_STATE au début de toutes les fonctions exportées dans les DLL normales liées de manière dynamique aux MFC.Cette macro définit l'état du module en cours comme étant celui de la DLL.Pour utiliser cette macro, ajoutez la ligne de code suivante au début des fonctions exportées de la DLL :
AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
WinMain - > DllMain
La bibliothèque MFC définit le point d'entrée standard Win32 DllMain qui initialise l'objet dérivé de CWinApp comme dans une application classique MFC.Placez tout le code d'initialisation des DLL dans la méthode d' InitInstance comme dans une application classique MFC.
Remarquez que le mécanisme CWinApp::Run ne s'applique pas à une DLL, car c'est l'application qui possède la pompe de messages principale.Si votre DLL affiche des boîtes de dialogue non modales ou possède une fenêtre frame principale propre, la pompe de messages principale de votre application doit appeler une routine exportée par la DLL qui appelle CWinApp::PreTranslateMessage.
Consultez l'exemple DLLScreenCap d'utilisation de cette fonction.
La fonction d' DllMain que MFC appelle la méthode d' CWinApp::ExitInstance de votre classe dérivée d' CWinAppavant son déchargement.
Lier votre DLL
Avec les DLL normales liées de manière statique aux MFC, vous devez lier votre DLL avec Nafxcwd.lib ou Nafxcw.lib et avec la version des runtimes C nommés Libcmt.lib.Ces bibliothèques sont prégénérées ni peuvent être installées en les spécifiant lorsque vous exécutez le programme d'installation de Visual C++.
Exemple de code
Consultez l'exemple de programme DLLScreenCap de concepts avancés par MFC pour obtenir un exemple complet.Plusieurs points sont à noter intéressantes dans cet exemple sont les suivants :
Les indicateurs de compilateur de la DLL et ceux de l'application sont différentes.
Les lignes de liaison et les fichiers .DEF pour la DLL et ceux de l'application sont différents.
L'application utilisant la DLL ne doit pas être en C++.
L'interface entre l'application et la DLL est une API utilisable par C ou C++ et est exportée à l'aide de DLLScreenCap.def.
L'exemple suivant illustre une API qui est définie dans une DLL normale liée de manière statique aux MFC.Dans cet exemple, la déclaration est intégrée dans un bloc d' extern "C" { } pour les utilisateurs C++.Cela présente plusieurs avantages.Tout d'abord, il rend votre API de DLL utilisables par des applications clientes non-C++.Ensuite, elle réduit la charge mémoire de la DLL car supprimer C++ n'est pas appliqué au nom exporté.Enfin, il facilite l'ajout explicite à un fichier .DEF (pour l'exportation par ordinal) en éliminant de supprimer de nom.
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct TracerData
{
BOOL bEnabled;
UINT flags;
};
BOOL PromptTraceFlags(TracerData FAR* lpData);
#ifdef __cplusplus
}
#endif
Les structures utilisées par l'API ne sont pas dérivées de classes MFC et sont définies dans l'en-tête API.Cela réduit la complexité de l'interface entre la DLL et l'application et rend la DLL utilisable par les programmes C.