Exportation et importation à l'aide de AFX_EXT_CLASS
Les DLL d'extension utilisent la macro AFX_EXT_CLASS pour exporter des classes ; les exécutables qui sont liés à la DLL d'extension utilisent cette macro pour importer des classes. La macro AFX_EXT_CLASS vous permet de réutiliser avec les exécutables liés à la DLL les fichiers d'en-tête que vous avez utilisés pour générer la DLL d'extension.
Dans le fichier d'en-tête de la DLL, ajoutez le mot clé AFX_EXT_CLASS à la déclaration de votre classe, de la manière suivante :
class AFX_EXT_CLASS CMyClass : public CDocument
{
// <body of class>
};
Cette macro est définie par les MFC en tant que __declspec(dllexport) lorsque les symboles de préprocesseur _AFXDLL et _AFXEXT sont définis. Mais la macro est définie en tant que __declspec(dllimport) quand le symbole _AFXDLL est défini et que le symbole _AFXEXT n'est pas défini. Lorsqu'il est défini, le symbole de préprocesseur _AFXDLL indique que la version partagée des MFC est utilisée par l'exécutable cible (une DLL ou une application). Quand _AFXDLL et _AFXEXT sont tous deux définis, l'exécutable cible est une DLL d'extension.
Comme AFX_EXT_CLASS est définie en tant que __declspec(dllexport) lors d'une exportation à partir d'une DLL d'extension, vous pouvez exporter des classes entières sans placer les noms décorés de tous les symboles de cette classe dans le fichier .def. Cette méthode est utilisée par l'exemple MFC DLLHUSK.
Bien que vous puissiez éviter de créer un fichier .def et tous les noms décorés de la classe avec cette méthode, il est plus efficace de créer un fichier .def, car les noms peuvent être exportés par ordinal. Pour utiliser la méthode d'exportation par fichier .def, placez le code suivant au début et à la fin du fichier d'en-tête :
#undef AFX_DATA
#define AFX_DATA AFX_EXT_DATA
// <body of your header file>
#undef AFX_DATA
#define AFX_DATA
Avertissement
Soyez vigilant lorsque vous exportez des fonctions inline, car elles peuvent donner lieu à des conflits de versions. Une fonction inline est développée en code d'application ; par conséquent, si vous réécrivez la fonction par la suite, celle-ci n'est mise à jour que si l'application elle-même est recompilée. En principe, les fonctions de la DLL peuvent être mises à jour sans régénération des applications qui les utilisent.
Exportation de membres individuels d'une classe
Vous souhaiterez peut-être parfois exporter des membres individuels de votre classe. Par exemple, si vous exportez une classe dérivée de CDialog, il se peut que vous n'ayez à exporter que le constructeur et l'appel à DoModal. Vous pouvez appliquer AFX_EXT_CLASS aux différents membres à exporter.
Par exemple :
class CExampleDialog : public CDialog
{
public:
AFX_EXT_CLASS CExampleDialog();
AFX_EXT_CLASS int DoModal();
...
// rest of class definition
...
};
Comme vous n'exportez plus tous les membres de la classe, vous risquez de rencontrer un autre problème en raison du mode de fonctionnement des macros MFC. Plusieurs des macros d'assistance des MFC déclarent ou définissent en fait des données membres. Par conséquent, ces données membres doivent également être exportées à partir de la DLL.
Par exemple, la macro DECLARE_DYNAMIC est définie de la façon suivante lors de la génération d'une DLL d'extension :
#define DECLARE_DYNAMIC(class_name) \
protected: \
static CRuntimeClass* PASCAL _GetBaseClass(); \
public: \
static AFX_DATA CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \
La ligne commençant par le modificateur AFX_DATA statique déclare un objet statique à l'intérieur de la classe. Pour exporter cette classe correctement et accéder aux informations d'exécution à partir d'un exécutable client, vous devez exporter cet objet statique. Dans la mesure où l'objet statique est déclaré avec le modificateur AFX_DATA, vous devez définir AFX_DATA en tant que __declspec(dllexport) seulement lors de la génération de la DLL et le définir en tant que __declspec(dllimport) lors de la génération de l'exécutable client. Comme AFX_EXT_CLASS est déjà définie de cette façon, il vous suffit de redéfinir AFX_DATA pour lui donner la même valeur que AFX_EXT_CLASS autour de la définition de votre classe.
Par exemple :
#undef AFX_DATA
#define AFX_DATA AFX_EXT_CLASS
class CExampleView : public CView
{
DECLARE_DYNAMIC()
// ... class definition ...
};
#undef AFX_DATA
#define AFX_DATA
Comme les MFC utilisent toujours le symbole AFX_DATA sur les éléments de données qu'elles définissent dans leurs macros, cette technique fonctionne pour tous les scénarios de ce type. Par exemple, elle fonctionne pour DECLARE_MESSAGE_MAP.
Notes
Si vous exportez la classe entière plutôt qu'une sélection de membres de la classe, les données membres statiques sont exportées automatiquement
Que voulez-vous faire ?
Exporter à partir d'une DLL à l'aide de __declspec(dllexport)
Exporter des fonctions C++ à utiliser dans des exécutables en langage C
Exporter des fonctions C à utiliser dans des exécutables en langage C ou C++
Importer dans une application à l'aide de __declspec(dllimport)