TN011: Utilizzo di MFC come parte di una DLL
Questa nota vengono illustrate le DLL regolari, che consentono di utilizzare la libreria MFC come parte dell'finestre libreria a collegamento (DLL) dinamico.Si presuppone la conoscenza delle DLL delle finestre e come compilarli.Per informazioni sulle DLL di estensione MFC, con cui è possibile creare estensioni alla libreria MFC, vedere Versione DLL di MFC.
Interfacce DLL
Le DLL regolari presuppongono le interfacce tra l'applicazione e la DLL vengono specificati nelle funzioni di tipo c o in classi in modo esplicito esportate.Le interfacce di classe MFC non è possibile esportare.
Se fosse una DLL che un'applicazione desidera utilizzare MFC, entrambi fanno il collegamento una scelta da utilizzare la versione condivisa delle librerie MFC o a in modo statico a una copia delle librerie.L'applicazione e la DLL sono entrambi utilizzare una delle versioni standard della libreria MFC.
Le DLL regolari verificano diversi vantaggi:
L'applicazione che utilizza la DLL non è necessario utilizzare MFC e non deve essere un'applicazione di Visual C++.
Con le DLL regolari collegate a MFC, le dimensioni della DLL dipende esclusivamente da MFC e dalle routine runtime c utilizzati e collegati.
Con le DLL regolari collegate a MFC in modo dinamico, un miglioramento in memoria di utilizzare la versione condivisa di MFC possono essere significativi.Tuttavia, è necessario distribuire le DLL, MFC<versione>DLL e il Msvvcrt condivisi<versione>dll, con la DLL.
La progettazione di DLL è indipendente dal modo in cui le classi sono implementate.La progettazione di DLL esporta solo alle API desiderato.Pertanto, se le modifiche di implementazione, le DLL regolari sono ancora valide.
Con le DLL regolari collegate a MFC, se la DLL e per l'applicazione utilizza MFC, non esistono problemi con l'applicazione che utilizza una versione diversa di MFC che la DLL o viceversa.Poiché la libreria MFC viene collegata in modo statico nelle DLL o EXE, non esiste una domanda relativa alla versione è.
Limitazioni dell'API
Alcune funzionalità MFC non si applica alla versione di DLL, o a causa delle limitazioni tecniche o perché questi servizi vengono generalmente forniti dall'applicazione.Con la versione corrente di MFC, l'unica funzione che non è applicabile è CWinApp::SetDialogBkColor.
Compilare la DLL
Quando si compilano le DLL regolari collegate a MFC, i simboli _USRDLL e a _WINDLL deve essere definito.Il codice della DLL deve essere compilato con le seguenti opzioni del compilatore:
/D_WINDLL indica la compilazione di una DLL
/D_USRDLL specificare compila una DLL regolare
È inoltre necessario definire questi simboli e utilizzare queste opzioni del compilatore quando si compila le DLL regolari collegate a MFC in modo dinamico.Inoltre, il simbolo _AFXDLL deve essere definito e il codice della DLL deve essere compilato con:
- /D_AFXDLL specifica che si compila una DLL regolare collegata a MFC
Le interfacce (API) tra l'applicazione e la DLL devono essere esplicitamente esportate.È consigliabile definire le interfacce per essere breve larghezza di banda e si utilizza solo interfacce di C# se possibile.Le interfacce dirette c# sono più facili da gestire che le classi più complesse di C++.
Inserire le API nell'intestazione separato che può essere inclusa da entrambi i file c e C++.Vedere l'intestazione ScreenCap.h nell'esempio DLLScreenCap di concetti avanzati MFC per un esempio.Per esportare le funzioni, fornirle nella sezione di EXPORTS del file di definizione di modulo (.DEF) o importare __declspec(dllexport) nelle definizioni di funzione.Utilizzare __declspec(dllimport) per importare queste funzioni nell'eseguibile client.
È necessario aggiungere la macro di AFX_MANAGE_STATE all'inizio di tutte le funzioni esportate dalle DLL regolari collegate a MFC in modo dinamico.Questa macro imposta lo stato del modulo corrente su quello della DLL.Per utilizzare questa macro, aggiungere la seguente riga di codice alle funzioni esportate dalla DLL:
AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
WinMain - > DllMain
La libreria MFC definisce il punto di ingresso standard Win32 DllMain che inizializza l'oggetto derivato CWinApp come in un'applicazione tipica MFC.Inserire tutto il codice di inizializzazione DLL-specifica nel metodo di InitInstance come in un'applicazione tipica MFC.
Tenere presente che il meccanismo CWinApp::Run non è applicabile a una DLL, poiché l'applicazione possiede il message pump principale.Se la DLL visualizzare finestre di dialogo non modali o dispone di una propria finestra cornice principale, il message pump principale dell'applicazione deve chiamare una routine esportata da DLL che chiama CWinApp::PreTranslateMessage.
Vedere l'esempio DLLScreenCap per l'utilizzo di tale funzione.
La funzione di DllMain che MFC fornisce chiamerà il metodo di CWinApp::ExitInstance della classe derivata da CWinAppprima che la DLL venga scaricata.
Collegare la DLL
Con le DLL regolari collegate a MFC, è necessario collegare la DLL con Nafxcwd.lib o Nafxcw.lib e con la versione del runtime C denominate Libcmt.lib.Queste librerie vengono precompilati e possono essere installate specificandoli quando si esegue il programma di installazione di Visual C++.
Codice di esempio
Vedere il programma di esempio DLLScreenCap di concetti avanzati MFC per un esempio completo.Alcune considerazioni interessante notare in questo esempio sono le seguenti:
I flag del compilatore della DLL e quelli dell'applicazione sono diversi.
Le righe di collegamento e i file def della DLL e quelli di applicazione sono differenti.
L'applicazione che utilizza la DLL non deve trovarsi in C++.
L'interfaccia tra l'applicazione e la DLL è un'api che è utilizzabile da C# o da C++ e viene esportato con DLLScreenCap.def.
Nell'esempio seguente viene illustrato un API definito in una DLL regolare con collegamento statico a MFC.In questo esempio, la dichiarazione è contenuta in un blocco di extern "C" { } per gli utenti C++.Questa operazione presenta diversi vantaggi.Innanzitutto, rende la DLL API utilizzabile dalle applicazioni client non C++.In secondo luogo, riduce l'overhead della DLL poiché l'applicazione del nome C++ non verrà applicata al nome esportato.Infine, semplifica in modo esplicito a un file def (per esportare in base al valore ordinale) non preoccuparsi per l'imposizione del nome.
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct TracerData
{
BOOL bEnabled;
UINT flags;
};
BOOL PromptTraceFlags(TracerData FAR* lpData);
#ifdef __cplusplus
}
#endif
Le strutture utilizzate dall'API non vengono derivate dalle classi MFC e definite nell'intestazione dell'API.In tal modo la complessità dell'interfaccia tra la DLL e l'applicazione e rende la DLL utilizzabile dai programmi C.