TN011: Bir DLL'in bir Parçası Olarak MFC Kullanma
Bu not, Windows dinamik bağlantı kitaplığının (DLL) bir parçası olarak MFC kitaplığını kullanmanıza olanak tanıyan normal MFC DLL'lerini açıklar. Windows DLL'lerini ve bunların nasıl derlendiğini bildiğiniz varsayılır. MFC kitaplığına uzantılar oluşturabileceğiniz MFC uzantısı DLL'leri hakkında bilgi için bkz . MFC'nin DLL Sürümü.
DLL Arabirimleri
normal MFC DLL'leri, uygulama ve DLL arasındaki arabirimlerin C benzeri işlevlerde veya açıkça dışarı aktarılan sınıflarda belirtildiğini varsayar. MFC sınıf arabirimleri dışarı aktarılamaz.
Hem DLL hem de uygulama MFC kullanmak istiyorsa, her ikisinin de MFC kitaplıklarının paylaşılan sürümünü kullanma veya kitaplıkların bir kopyasına statik olarak bağlanma seçeneği vardır. Hem uygulama hem de DLL, MFC kitaplığının standart sürümlerinden birini kullanabilir.
normal MFC DLL'lerinin çeşitli avantajları vardır:
DLL kullanan uygulamanın MFC kullanması gerekmez ve visual C++ uygulaması olması gerekmez.
MFC'ye statik olarak bağlanan normal MFC DLL'lerinde, DLL'nin boyutu yalnızca kullanılan ve bağlanan MFC ve C çalışma zamanı yordamlarına bağlıdır.
MFC'ye dinamik olarak bağlanan normal MFC DLL'leri ile, MFC'nin paylaşılan sürümünün kullanılmasından bellekte tasarruf edilmesi önemli olabilir. Ancak, paylaşılan DLL'leri, Mfc version.dll> ve Msvvcrt<version.dll'yi> DLL'nizle dağıtmanız gerekir.<
DLL tasarımı, sınıfların nasıl uygulandığından bağımsızdır. DLL tasarımınız yalnızca istediğiniz API'lere dışarı aktarılır. Sonuç olarak, uygulama değişirse normal MFC DLL'leri geçerli olmaya devam eder.
MFC'ye statik olarak bağlanan normal MFC DLL'leri ile hem DLL hem de uygulama MFC kullanıyorsa, uygulamada DLL'den farklı bir MFC sürümü isteyen veya tam tersi olan bir sorun yoktur. MFC kitaplığı her DLL veya EXE'ye statik olarak bağlı olduğundan, hangi sürüme sahip olduğunuz konusunda hiçbir soru yoktur.
API Sınırlamaları
Bazı MFC işlevleri, teknik sınırlamalar nedeniyle veya bu hizmetler genellikle uygulama tarafından sağlandığından DLL sürümü için geçerli değildir. MFC'nin geçerli sürümüyle, geçerli olmayan tek işlevdir CWinApp::SetDialogBkColor
.
DLL'nizi Oluşturma
MFC'ye statik olarak bağlanan normal MFC DLL'lerini derlerken simgeler _USRDLL
ve _WINDLL
tanımlanmalıdır. DLL kodunuz da aşağıdaki derleyici anahtarlarıyla derlenmelidir:
/D_WINDLL derlemenin bir DLL için olduğunu belirtir
/D_USRDLL , normal bir MFC DLL oluşturduğunuzu belirtir
Ayrıca bu simgeleri tanımlamanız ve MFC'ye dinamik olarak bağlanan normal MFC DLL'lerini derlerken bu derleyici anahtarlarını kullanmanız gerekir. Ayrıca, simge _AFXDLL
tanımlanmalıdır ve DLL kodunuz şu şekilde derlenmelidir:
- /D_AFXDLL , MFC'ye dinamik olarak bağlanan normal bir MFC DLL oluşturduğunuzu belirtir
Uygulama ve DLL arasındaki arabirimler (API'ler) açıkça dışarı aktarılmalıdır. Arabirimlerinizi düşük bant genişliğine sahip olacak şekilde tanımlamanızı ve bunu yapabilirseniz yalnızca C arabirimlerini kullanmanızı öneririz. Doğrudan C arabirimlerinin bakımı daha karmaşık C++ sınıflarından daha kolaydır.
API'lerinizi hem C hem de C++ dosyaları tarafından eklenebilen ayrı bir üst bilgi içine yerleştirin. Bir örnek için MFC Gelişmiş Kavramlar örneği DLLScreenCap içindeki ScreenCap.h üst bilgisine bakın. İşlevlerinizi dışarı aktarmak için bunları modül tanım dosyanızın ( bölümüne girin EXPORTS
. DEF) veya işlev tanımlarınıza ekleyin __declspec(dllexport)
. Bu işlevleri istemci yürütülebilir dosyaya aktarmak için kullanın __declspec(dllimport)
.
MFC'ye dinamik olarak bağlanan normal MFC DLL'lerinde dışarı aktarılan tüm işlevlerin başına AFX_MANAGE_STATE makroyu eklemeniz gerekir. Bu makro geçerli modül durumunu DLL için bir olarak ayarlar. Bu makroyu kullanmak için, DLL'den dışarı aktarılan işlevlerin başına aşağıdaki kod satırını ekleyin:
AFX_MANAGE_STATE(AfxGetStaticModuleState( ))
WinMain -> DllMain
MFC kitaplığı, tipik bir MFC uygulamasında olduğu gibi CWinApp türetilmiş nesnenizi başlatan standart Win32 DllMain
giriş noktasını tanımlar. Dll'ye özgü tüm başlatmaları tipik bir MFC uygulamasında olduğu gibi InitInstance yöntemine yerleştirin.
Ana ileti pompasının sahibi uygulama olduğundan CWinApp::Run mekanizmasının DLL'ye uygulanmadığını unutmayın. DLL'niz modsuz iletişim kutuları görüntülüyorsa veya kendi ana çerçeve penceresine sahipse, uygulamanızın ana ileti pompası CWinApp::P reTranslateMessage çağrısında bulunan DLL dışarı aktarılan yordamı çağırmalıdır.
Bu işlevin kullanımı için DLLScreenCap örneğine bakın.
MFC'nin DllMain
sağladığı işlev, DLL kaldırılmadan önce türetilen CWinApp
sınıfınızın CWinApp::ExitInstance yöntemini çağırır.
DLL'nizi Bağlama
MFC'ye statik olarak bağlanan normal MFC DLL'leri ile DLL'nizi Nafxcwd.lib veya Nafxcw.lib ile ve C çalışma zamanlarının Libcmt.lib adlı sürümüyle bağlamanız gerekir. Bu kitaplıklar önceden oluşturulmuş ve Visual C++ kurulumunu çalıştırdığınızda belirtilerek yüklenebilir.
Örnek Kod
Tam bir örnek için bkz. MFC Gelişmiş Kavramlar örnek programı DLLScreenCap. Bu örnekte dikkate alınacak birkaç ilginç nokta şunlardır:
DLL'nin ve uygulamanın derleyici bayrakları farklıdır.
Bağlantı çizgileri ve . DLL için DEF dosyaları ve uygulama için olanlar farklıdır.
DLL'yi kullanan uygulamanın C++ içinde olması gerekmez.
Uygulama ve DLL arasındaki arabirim, C veya C++ tarafından kullanılabilen ve DLLScreenCap.def ile dışarı aktarılan bir API'dir.
Aşağıdaki örnekte, MFC'ye statik olarak bağlanan normal bir MFC DLL'sinde tanımlanan bir API gösterilmektedir. Bu örnekte, bildirim C++ kullanıcıları için bir extern "C" { }
blok içine alınır. Bunun çeşitli avantajları vardır. İlk olarak, DLL API'lerinizi C++ olmayan istemci uygulamaları tarafından kullanılabilir hale getirir. İkinci olarak, C++ adı mangling dışarı aktarılan ada uygulanmayacağından DLL ek yükünü azaltır. Son olarak, bir öğesine açıkça eklemeyi kolaylaştırır. AD mangling konusunda endişelenmenize gerek kalmadan DEF dosyası (sıralı olarak dışarı aktarma için).
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct TracerData
{
BOOL bEnabled;
UINT flags;
};
BOOL PromptTraceFlags(TracerData FAR* lpData);
#ifdef __cplusplus
}
#endif
API tarafından kullanılan yapılar MFC sınıflarından türetilmemiş ve API üst bilgisinde tanımlanmıştır. Bu, DLL ile uygulama arasındaki arabirimin karmaşıklığını azaltır ve DLL'yi C programları tarafından kullanılabilir hale getirir.