Partager via


TN011 : utilisation de MFC dans le cadre d'une DLL

Cette note décrit les DLL MFC standard, qui vous permettent d’utiliser la bibliothèque MFC dans le cadre d’une bibliothèque de liens dynamiques Windows (DLL). Cela suppose une certaine familiarisation avec les DLL Windows et leur mode de création. Pour plus d’informations sur les DLL d’extension MFC, avec lesquelles vous pouvez créer des extensions dans la bibliothèque MFC, consultez la version DLL de MFC.

DLL Interfaces

Les DLL MFC standard supposent que les interfaces entre l’application et la DLL sont spécifiées dans des fonctions de type C ou des classes exportées explicitement. Les interfaces de classe MFC ne peuvent pas être exportées.

Si une DLL et une application veulent utiliser MFC, elles peuvent toutes deux utiliser la version partagée des bibliothèques MFC ou utiliser un lien statiquement vers une copie des bibliothèques. L'application et la DLL peuvent toutes deux utiliser l'une des versions standard de la bibliothèque MFC.

Les DLL MFC régulières présentent plusieurs avantages :

  • Une application qui utilise la DLL ne doit pas utiliser MFC et ne doit pas nécessairement être une application Visual C++.

  • Avec des DLL MFC régulières qui relient statiquement MFC à MFC, la taille de la DLL dépend uniquement des routines de runtime MFC et C utilisées et liées.

  • Avec des DLL MFC régulières qui relient dynamiquement MFC, les économies de mémoire à l’aide de la version partagée de MFC peuvent être significatives. Toutefois, vous devez distribuer les DLL partagées, Mfc version.dll> et Msvvcrt<version.dll>, avec votre DLL.<

  • La création de la DLL est indépendante de la façon dont les classes sont implémentées. La conception de DLL exporte uniquement pour les API que vous souhaitez. Par conséquent, si l’implémentation change, les DLL MFC régulières sont toujours valides.

  • Avec des DLL MFC standard qui sont liées statiquement à MFC, si la DLL et l’application utilisent MFC, il n’existe aucun problème avec l’application qui souhaite une version différente de MFC que la DLL ou inversement. Étant donné que la bibliothèque MFC est statiquement liée dans chaque DLL ou EXE, il n'y a aucun problème avec la version dont vous disposez.

Limitations API

Certaines fonctionnalités de MFC ne s'appliquent pas à la version DLL, soit en raison des 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.

Création de la DLL

Lors de la compilation de DLL MFC régulières qui relient statiquement MFC à MFC, les symboles _USRDLL et _WINDLL doivent être définis. Le code DLL doit également être compilé avec les commutateurs de compilation suivants :

  • /D_WINDLL signifie que la compilation est destinée à une DLL

  • /D_USRDLL spécifie que vous créez une DLL MFC standard

Vous devez également définir ces symboles et utiliser ces commutateurs de compilateur lorsque vous compilez des DLL MFC régulières qui lient dynamiquement à MFC. En outre, le symbole _AFXDLL doit être défini et le code DLL doit être compilé avec :

  • /D_AFXDLL spécifie que vous créez une DLL MFC standard qui lie dynamiquement à MFC

Les interfaces (API) entre l'application et la DLL doivent être explicitement exportées. Nous vous recommandons de définir des interfaces à faible bande passante, et si possible, d'utiliser uniquement des interfaces C. Il est plus facile de gérer les interfaces C directes que les classes C++ plus complexes.

Placez les API dans en-tête distinct qui peut être inclus dans les fichiers C et C++. Consultez l’en-tête ScreenCap.h dans l’exemple DLLScreenCap de MFC pour obtenir un exemple. Pour exporter les fonctions, écrivez-les dans la section EXPORTS de votre fichier de définition de module (.DEF) ou incluez __declspec(dllexport) dans les définitions de fonction. Utilisez __declspec(dllimport) pour importer ces fonctions dans le fichier exécutable client.

Vous devez ajouter la macro AFX_MANAGE_STATE au début de toutes les fonctions exportées dans des DLL MFC régulières qui lient dynamiquement à MFC. La macro définit l'état du module en cours à celui de la DLL. Pour utiliser cette macro, ajoutez la ligne de code suivante au début des fonctions exportées à partir de la DLL :

AFX_MANAGE_STATE(AfxGetStaticModuleState( ))

WinMain -> DllMain

La bibliothèque MFC définit le point d’entrée Win32 DllMain standard qui initialise votre objet dérivé CWinApp comme dans une application MFC classique. Placez l’initialisation spécifique à la DLL dans la méthode InitInstance comme dans une application MFC classique.

Notez que le mécanisme CWinApp ::Run ne s’applique pas à une DLL, car l’application possède la pompe de message principale. Si votre DLL affiche des dialogues sans mode ou dispose d’une fenêtre de trame principale, la pompe de messages principale de votre application doit appeler une routine exportée par DLL qui appelle CWinApp ::P reTranslateMessage.

Pour obtenir un exemple de cette fonction, consultez l'exemple DLLScreenCap.

La DllMain fonction que MFC fournit appelle la méthode CWinApp ::ExitInstance de votre classe dérivée CWinApp avant que la DLL ne soit déchargée.

Liaison de votre DLL

Avec des DLL MFC régulières qui relient statiquement MFC à MFC, vous devez lier votre DLL à 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 et 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 MFC pour obtenir un exemple complet. Plusieurs choses intéressantes à noter dans cet exemple :

  • Les indicateurs de compilateur de la DLL et ceux de l'application sont différents.

  • Les lignes de liaison et les fichiers .DEF pour la DLL et celles de l'application sont différentes.

  • Une application qui utilise la DLL ne doit pas être en C++.

  • L'interface entre l'application et la DLL est une API qui est utilisable par C ou C++ et est exportée avec DLLScreenCap.def.

L’exemple suivant illustre une API définie dans une DLL MFC standard qui lie statiquement à MFC. Dans cet exemple, la déclaration est englobée dans un bloc extern "C" { } pour les utilisateurs C++. Cela a plusieurs avantages. Tout d'abord, elle permet l'utilisation des API de votre DLL par des applications clientes non-C++. Ensuite, elle réduit la charge mémoire de la DLL dans la mesure où la convention des noms C++ n'est pas appliquée au nom exporté. Enfin, elle facilite l'ajout explicite de fonctions à un fichier .DEF (en vue d'une exportation ordinale) en éliminant la contrainte de la convention des noms.

#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 des classes de MFC et sont définies dans l'en-tête d'API. Il est ainsi possible de réduire la complexité de l'interface entre la DLL et l'application et rend la DLL utilisable pour les programmes C.

Voir aussi

Notes techniques par numéro
Notes techniques par catégorie