Aracılığıyla paylaş


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.

Ayrıca bkz.

Sayıya Göre Teknik Notlar
Kategoriye Göre Teknik Notlar