TN011: utilizzo di MFC come parte di una DLL

Questa nota descrive le normali DLL MFC, che consentono di usare la libreria MFC come parte di una libreria a collegamento dinamico (DLL) di Windows. Presuppone che tu abbia familiarità con le DLL di Windows e come compilarle. Per informazioni sulle DLL dell'estensione MFC, con cui è possibile creare estensioni per la libreria MFC, vedere Versione DLL di MFC.

Interfacce DLL

le NORMALI DLL MFC presuppongono che le interfacce tra l'applicazione e la DLL siano specificate nelle funzioni simili a C o nelle classi esportate in modo esplicito. Le interfacce della classe MFC non possono essere esportate.

Se sia una DLL che un'applicazione vogliono usare MFC, entrambe hanno la possibilità di usare la versione condivisa delle librerie MFC o di collegarsi in modo statico a una copia delle librerie. L'applicazione e la DLL possono usare entrambe una delle versioni standard della libreria MFC.

le DLL MFC regolari presentano diversi vantaggi:

  • L'applicazione che usa la DLL non deve usare MFC e non deve essere un'applicazione Visual C++.

  • Con le normali DLL MFC collegate in modo statico a MFC, le dimensioni della DLL dipendono solo dalle routine di runtime MFC e C usate e collegate.

  • Con le normali DLL MFC che si collegano dinamicamente a MFC, i risparmi in memoria derivanti dall'uso della versione condivisa di MFC possono essere significativi. Tuttavia, è necessario distribuire le DLL condivise, Mfc version.dll> e Msvvcrt<version.dll>, con la DLL.<

  • La progettazione della DLL è indipendente dalla modalità di implementazione delle classi. La progettazione della DLL esporta solo nelle API desiderate. Di conseguenza, se l'implementazione cambia, le NORMALI DLL MFC sono ancora valide.

  • Con le normali DLL MFC che si collegano in modo statico a MFC, se entrambe le DLL e le applicazioni usano MFC, non ci sono problemi con l'applicazione che vuole una versione diversa di MFC rispetto alla DLL o viceversa. Poiché la libreria MFC è collegata in modo statico a ogni DLL o EXE, non c'è dubbio sulla versione in uso.

Limitazioni api

Alcune funzionalità MFC non si applicano alla versione dll, a causa di limitazioni tecniche o perché tali servizi sono in genere forniti dall'applicazione. Con la versione corrente di MFC, l'unica funzione non applicabile è CWinApp::SetDialogBkColor.

Compilazione della DLL

Quando si compilano dll MFC regolari che si collegano in modo statico a MFC, i _USRDLL simboli e _WINDLL devono essere definiti. Il codice DLL deve anche essere compilato con le opzioni del compilatore seguenti:

  • /D_WINDLL indica che la compilazione è per una DLL

  • /D_USRDLL specifica che si sta creando una normale DLL MFC

È inoltre necessario definire questi simboli e usare queste opzioni del compilatore quando si compilano normali DLL MFC che si collegano dinamicamente a MFC. Inoltre, il simbolo _AFXDLL deve essere definito e il codice DLL deve essere compilato con:

  • /D_AFXDLL specifica che si sta creando una normale DLL MFC che collega in modo dinamico a MFC

Le interfacce (API) tra l'applicazione e la DLL devono essere esportate in modo esplicito. È consigliabile definire le interfacce in modo che siano a larghezza di banda ridotta e usare solo le interfacce C, se possibile. Le interfacce C dirette sono più facili da gestire rispetto a classi C++ più complesse.

Inserire le API in un'intestazione separata che può essere inclusa sia dai file C che da C++. Vedere l'intestazione ScreenCap.h nell'esempio MFC Advanced Concepts DLLScreenCap per un esempio. Per esportare le funzioni, immetterle nella EXPORTS sezione del file di definizione del modulo (. DEF) o includere __declspec(dllexport) nelle definizioni di funzione. Usare __declspec(dllimport) per importare queste funzioni nel file eseguibile del client.

È necessario aggiungere la macro AFX_MANAGE_STATE all'inizio di tutte le funzioni esportate nelle normali DLL MFC che si collegano dinamicamente a MFC. Questa macro imposta lo stato corrente del modulo su quello per la DLL. Per usare questa macro, aggiungere la riga di codice seguente all'inizio delle funzioni esportate dalla DLL:

AFX_MANAGE_STATE(AfxGetStaticModuleState( ))

WinMain -> DllMain

La libreria MFC definisce il punto di ingresso Win32 DllMain standard che inizializza l'oggetto derivato CWinApp come in una tipica applicazione MFC. Inserire tutta l'inizializzazione specifica della DLL nel metodo InitInstance come in un'applicazione MFC tipica.

Si noti che il meccanismo CWinApp::Run non si applica a una DLL, perché l'applicazione è proprietaria del pump di messaggi principale. Se la DLL visualizza finestre di dialogo senza modalità o ha una finestra cornice principale di propria proprietà, il message pump principale dell'applicazione deve chiamare una routine esportata da DLL che chiama CWinApp::P reTranslateMessage.

Vedere l'esempio DLLScreenCap per l'uso di questa funzione.

La DllMain funzione fornita da MFC chiamerà il metodo CWinApp::ExitInstance della classe derivata prima CWinApp che la DLL venga scaricata.

Collegamento della DLL

Con le normali DLL MFC collegate in modo statico a MFC, è necessario collegare la DLL con Nafxcwd.lib o Nafxcw.lib e con la versione dei runtime C denominati Libcmt.lib. Queste librerie sono pre-compilate e possono essere installate specificandole durante l'esecuzione dell'installazione di Visual C++.

Codice di esempio

Per un esempio completo, vedere il programma di esempio MFC Advanced Concepts DLLScreenCap. Di seguito sono riportati alcuni aspetti interessanti da notare in questo esempio:

  • I flag del compilatore della DLL e quelli dell'applicazione sono diversi.

  • Linee di collegamento e . I file DEF per la DLL e quelli per l'applicazione sono diversi.

  • L'applicazione che usa la DLL non deve essere in C++.

  • L'interfaccia tra l'applicazione e la DLL è un'API utilizzabile da C o C++ ed esportata con DLLScreenCap.def.

L'esempio seguente illustra un'API definita in una normale DLL MFC collegata in modo statico a MFC. In questo esempio la dichiarazione è racchiusa in un extern "C" { } blocco per gli utenti C++. Questo presenta diversi vantaggi. In primo luogo, rende le API DLL utilizzabili dalle applicazioni client non C++. In secondo luogo, riduce il sovraccarico della DLL perché il mangling dei nomi C++ non verrà applicato al nome esportato. Infine, semplifica l'aggiunta esplicita di a un oggetto . File DEF (per l'esportazione in base all'ordinale) senza doversi preoccupare del mangling dei nomi.

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

struct TracerData
{
    BOOL bEnabled;
    UINT flags;
};

BOOL PromptTraceFlags(TracerData FAR* lpData);

#ifdef __cplusplus
}
#endif

Le strutture usate dall'API non sono derivate dalle classi MFC e sono definite nell'intestazione DELL'API. Ciò riduce la complessità dell'interfaccia tra la DLL e l'applicazione e rende la DLL utilizzabile dai programmi C.

Vedi anche

Note tecniche per numero
Note tecniche per categoria