MFC uzantısı DLL’leri
MFC uzantı DLL'i, genellikle mevcut Microsoft Foundation Sınıf Kitaplığı sınıflarından türetilen yeniden kullanılabilir sınıfları uygulayan bir DLL'dir.
MFC uzantı DLL'sinin özellikleri ve gereksinimleri şunlardır:
İstemci yürütülebilir dosyası tanımlı olarak
_AFXDLL
derlenmiş bir MFC uygulaması olmalıdır.MFC uzantısı DLL'leri, MFC'ye dinamik olarak bağlı normal bir MFC DLL'leri tarafından da kullanılabilir.
MFC uzantısı DLL'leri tanımlı olarak
_AFXEXT
derlenmelidir. Bu da tanımlanmaya zorlar_AFXDLL
ve MFC üst bilgi dosyalarından doğru bildirimlerin çekilmesini sağlar. Ayrıca, DLL'yi oluştururken olarak__declspec(dllexport)
tanımlanmasını sağlarAFX_EXT_CLASS
. Bu, MFC uzantı DLL'nizdeki sınıfları bildirmek için bu makroyu kullanıyorsanız gereklidir.MFC uzantısı DLL'leri, öğesinden
CWinApp
türetilen bir sınıfın örneğini oluşturmamalı, ancak bu nesneyi sağlamak için istemci uygulamasına (veya DLL'ye) bağımlı olmalıdır.Ancak MFC uzantısı DLL'leri bir
DllMain
işlev sağlamalı ve gerekli başlatmaları orada yapmalıdır.
Uzantı DLL'leri, MFC'nin dinamik bağlantı kitaplığı sürümü (MFC'nin paylaşılan sürümü olarak da bilinir) kullanılarak oluşturulur. Yalnızca MFC'nin paylaşılan sürümüyle oluşturulan MFC yürütülebilir dosyaları (uygulamalar veya normal MFC DLL'leri) bir MFC uzantısı DLL kullanabilir. hem istemci uygulaması hem de MFC uzantı DLL'sinin aynı MFCx0.dll sürümünü kullanması gerekir. MFC uzantı DLL'siyle, MFC'den yeni özel sınıflar türetebilir ve ardından DLL'nizi çağıran uygulamalara bu genişletilmiş MFC sürümünü sunabilirsiniz.
Uzantı DLL'leri, MFC türetilmiş nesneleri uygulama ve DLL arasında geçirmek için de kullanılabilir. Geçirilen nesneyle ilişkili üye işlevleri, nesnenin oluşturulduğu modülde bulunur. MFC'nin paylaşılan DLL sürümü kullanılırken bu işlevler düzgün şekilde dışarı aktarıldığından, MFC veya MFC türetilmiş nesne işaretçilerini bir uygulama ile yüklediği MFC uzantısı DLL'leri arasında serbestçe geçirebilirsiniz.
MFC uzantısı DLL'leri, MFC'nin paylaşılan sürümünü, uygulamanın MFC'nin paylaşılan DLL sürümünü kullandığı gibi kullanır ve dikkat edilmesi gereken birkaç nokta daha vardır:
Türetilmiş bir
CWinApp
nesnesi yok. İstemci uygulamasınınCWinApp
türetilmiş nesnesiyle çalışmalıdır. Bu, istemci uygulamasının ana ileti pompasına, boşta döngüsüne vb. sahip olduğu anlamına gelir.işlevini çağırır
AfxInitExtensionModule
DllMain
. Bu işlevin dönüş değeri denetlenmelidir. değerindenAfxInitExtensionModule
sıfır değer döndürülürse işlevinizdenDllMain
0 döndürür.MFC uzantısı DLL'si nesneleri veya kaynakları uygulamaya aktarmak
CRuntimeClass
istiyorsa başlatma sırasında bir CDynLinkLibrary nesnesi oluşturur.
MFC'nin 4.0 sürümünden önce, bu tür DLL'ler AFXDLL olarak adlandırılıyordu. AFXDLL, DLL oluşturulurken tanımlanan önişlemci simgesine başvurur _AFXDLL
.
MFC'nin paylaşılan sürümü için içeri aktarma kitaplıkları, MFC DLL'leri için adlandırma kuralları bölümünde açıklanan kurala göre adlandırılır. Visual Studio, MFC DLL'lerinin önceden oluşturulmuş sürümlerinin yanı sıra uygulamalarınızla birlikte kullanabileceğiniz ve dağıtabileceğiniz bir dizi MFC dışı DLL sağlar. Bunlar, Program Files\Microsoft Visual Studio klasörüne yüklenen Redist.txt belgelenmiştir.
Bir .def dosyası kullanarak dışarı aktarıyorsanız, üst bilgi dosyanızın başına ve sonuna aşağıdaki kodu yerleştirin:
#undef AFX_DATA
#define AFX_DATA AFX_EXT_DATA
// <body of your header file>
#undef AFX_DATA
#define AFX_DATA
Bu dört satır, kodunuzun bir MFC uzantısı DLL'i için doğru derlendiğinden emin olun. Bu dört satırın dışında bırakılması DLL'nizin yanlış derlenip bağlanmasına neden olabilir.
MFC veya MFC türetilmiş nesne işaretçisini bir MFC DLL'sine veya MFC DLL'sinden geçirmeniz gerekiyorsa, DLL bir MFC uzantısı DLL olmalıdır. Geçirilen nesneyle ilişkili üye işlevleri, nesnenin oluşturulduğu modülde bulunur. MFC'nin paylaşılan DLL sürümü kullanılırken bu işlevler düzgün şekilde dışarı aktarıldığından, MFC veya MFC türetilmiş nesne işaretçilerini bir uygulama ile yüklediği MFC uzantısı DLL'leri arasında serbestçe geçirebilirsiniz.
C++ ad düzenleme ve dışarı aktarma sorunları nedeniyle, MFC uzantısı DLL'sinden dışarı aktarma listesi, farklı platformlar için aynı DLL ve DLL'lerin hata ayıklama ve perakende sürümleri arasında farklı olabilir. Perakende MFCx0.dll yaklaşık 2.000 dışarı aktarılan giriş noktası vardır; hata ayıklama MFCx0D.dll yaklaşık 3.000 dışarı aktarılan giriş noktası vardır.
Bellek Yönetimi
bir istemci uygulamasının adres alanına yüklenen MFCx0.dll ve tüm MFC uzantısı DLL'leri aynı uygulamadaymış gibi aynı bellek ayırıcısını, kaynak yüklemesini ve diğer MFC genel durumlarını kullanır. MFC DLL olmayan kitaplıklar ve normal MFC DLL'leri tam tersini yaptığı ve her DLL'nin kendi bellek havuzundan ayırması nedeniyle bu önemli bir durumdur.
Bir MFC uzantı DLL'i bellek ayırırsa, bu bellek uygulama tarafından ayrılan diğer tüm nesnelerle serbestçe kesişebilir. Ayrıca, MFC'ye dinamik olarak bağlanan bir uygulama başarısız olursa, işletim sisteminin korunması DLL'yi paylaşan diğer tüm MFC uygulamalarının bütünlüğünü korur.
Benzer şekilde, kaynakları yüklenecek geçerli yürütülebilir dosya gibi diğer genel MFC durumları da istemci uygulaması ile tüm MFC uzantısı DLL'leri ve MFCx0.dll arasında paylaşılır.
Kaynakları ve Sınıfları Paylaşma
Kaynakları dışarı aktarma işlemi bir kaynak listesi aracılığıyla yapılır. Her uygulama, CDynLinkLibrary nesnelerinin tek bağlantılı bir listesini içerir. Kaynak ararken, kaynakları yükleyen standart MFC uygulamalarının çoğu önce geçerli kaynak modülüne (AfxGetResourceHandle
) bakar ve kaynak bulunamazsa, istenen kaynağı yüklemeye çalışan CDynLinkLibrary nesnelerinin listesi görüntülenir.
Listede yürümenin, biraz daha yavaş olması ve kaynak kimliği aralıklarının yönetilmesini gerektirmesi dezavantajları vardır. Birkaç MFC uzantısı DLL'sine bağlanan bir istemci uygulamasının DLL örneği tanıtıcısını belirtmek zorunda kalmadan DLL tarafından sağlanan herhangi bir kaynağı kullanabilmesi avantajına sahiptir. AfxFindResourceHandle
, belirli bir eşleşmeyi aramak için kaynak listesinde yürümek için kullanılan bir API'dir. Kaynağın adını ve türünü alır ve ilk bulunduğu kaynak tutamacını (veya NULL) döndürür.
Listede gezinmek ve yalnızca belirli bir yerden kaynakları yüklemek istemiyorsanız, eski tanıtıcıyı kaydetmek ve AfxSetResourceHandle
yeni tanıtıcıyı ayarlamak için ve işlevlerini AfxGetResourceHandle
kullanın. İstemci uygulamasına dönmeden önce eski kaynak tanıtıcısını geri yüklemeyi unutmayın. Menüyü açıkça yüklemek için bu yaklaşımı kullanma örneği için bkz. MFC örnek DLLHUSK içindeki Testdll2 .cpp.
MFC adı verilen MFC nesnelerinin dinamik olarak oluşturulması benzerdir. MFC nesne seri durumdan çıkarma mekanizmasının CRuntimeClass
, daha önce depolananlara göre gerekli türde C++ nesnelerini dinamik olarak oluşturarak yeniden oluşturabilmesi için tüm nesnelerin kayıtlı olması gerekir.
MFC örnek DLLHUSK örneğinde, liste şuna benzer:
head -> DLLHUSK.EXE - or - DLLHUSK.EXE
| |
TESTDLL2.DLL TESTDLL2.DLL
| |
TESTDLL1.DLL TESTDLL1.DLL
| |
MFCOxxD.DLL |
| |
MFCDxxD.DLL |
| |
MFCxxD.DLL MFCxx.DLL
burada xx sürüm numarasıdır; örneğin, 42 sürüm 4.2'yi temsil eder.
MFCxx.dll genellikle kaynak ve sınıf listesinde son sırada yer alır. MFCxx.dll, tüm standart komut kimlikleri için istem dizeleri dahil olmak üzere tüm standart MFC kaynaklarını içerir. Listenin sonuna yerleştirmek DLL'lerin ve istemci uygulamasının kendi standart MFC kaynaklarının kopyasına sahip olmamasını, bunun yerine MFCxx.dll paylaşılan kaynaklara güvenmesini sağlar.
Tüm DLL'lerin kaynaklarını ve sınıf adlarını istemci uygulamasının ad alanıyla birleştirmek, hangi kimlikleri veya adları seçtiğinize dikkat etmenizi gerektiren bir dezavantaja sahiptir.
DLLHUSK örneği, paylaşılan kaynak adı alanını birden çok üst bilgi dosyası kullanarak yönetir.
MFC uzantı DLL'nizin her uygulama için ek veri tutması gerekiyorsa, CDynLinkLibrary'den yeni bir sınıf türetebilir ve içinde DllMain
oluşturabilirsiniz. DLL çalıştırılırken, geçerli uygulamanın CDynLinkLibrary nesneleri listesini denetleyerek söz konusu MFC uzantısı DLL'sinin listesini bulabilir.