Menggunakan DLL ekstensi MFC Database, OLE, dan Soket di DLL MFC reguler
Saat menggunakan DLL ekstensi MFC dari DLL MFC reguler, jika DLL ekstensi MFC tidak dikabeli ke dalam CDynLinkLibrary
rantai objek DLL MFC reguler, Anda mungkin mengalami satu atau beberapa masalah terkait. Karena versi debug MFC Database, OLE, dan Sockets mendukung DLL diimplementasikan sebagai DLL ekstensi MFC, Anda mungkin melihat masalah serupa jika Anda menggunakan fitur MFC ini, bahkan jika Anda tidak secara eksplisit menggunakan DLL ekstensi MFC Anda sendiri. Beberapa gejalanya adalah:
Saat mencoba mendeserialisasi objek dari jenis kelas yang ditentukan dalam DLL ekstensi MFC, pesan "Peringatan: Tidak dapat memuat CYourClass dari arsip. Kelas tidak ditentukan." muncul di jendela debug TRACE dan objek gagal diserialisasikan.
Pengecualian yang menunjukkan kelas buruk mungkin dilemparkan.
Sumber daya yang disimpan di DLL ekstensi MFC gagal dimuat karena
AfxFindResourceHandle
mengembalikanNULL
atau handel sumber daya yang salah.DllGetClassObject
, ,DllCanUnloadNow
danUpdateRegistry
fungsiCOleObjectFactory
anggota ,Revoke
,RevokeAll
, danRegisterAll
gagal menemukan pabrik kelas yang ditentukan dalam DLL ekstensi MFC.AfxDoForAllClasses
tidak berfungsi untuk kelas apa pun di DLL ekstensi MFC.Database MFC standar, soket, atau sumber daya OLE gagal dimuat. Misalnya,
AfxLoadString(AFX_IDP_SQL_CONNECT_FAIL)
mengembalikan string kosong, bahkan ketika DLL MFC reguler menggunakan kelas Database MFC dengan benar.
Solusi untuk masalah ini adalah membuat dan mengekspor fungsi inisialisasi CDynLinkLibrary
di DLL ekstensi MFC yang membuat objek. Panggil fungsi inisialisasi ini persis sekali dari setiap DLL MFC reguler yang menggunakan DLL ekstensi MFC.
Dukungan Soket MFC OLE, MFC Database (atau DAO), atau MFC
Jika Anda menggunakan dukungan MFC OLE, MFC Database (atau DAO), atau MFC Sockets di DLL MFC reguler Anda, masing-masing, DLL MFCOxxD.dll
ekstensi MFC debug MFC, , , MFCDxxD.dll
dan MFCNxxD.dll
(di mana xx adalah nomor versi) ditautkan secara otomatis. Panggil fungsi inisialisasi yang telah ditentukan sebelumnya untuk setiap DLL yang Anda gunakan:
Untuk dukungan database, tambahkan panggilan ke
AfxDbInitModule
DLL MFC reguler Anda dalam fungsinyaCWinApp::InitInstance
. Pastikan panggilan ini terjadi sebelum panggilan kelas dasar atau kode tambahan apa pun yang mengaksesMFCDxxD.dll
. Fungsi ini tidak mengambil parameter dan mengembalikanvoid
.Untuk dukungan OLE, tambahkan panggilan ke
AfxOleInitModule
DLL MFC reguler Anda, fungsinyaCWinApp::InitInstance
. Fungsi memanggilCOleControlModule::InitInstance
AfxOleInitModule
sudah, jadi jika Anda membangun kontrol OLE dan menggunakanCOleControlModule
, Anda tidak boleh menambahkan panggilan ini keAfxOleInitModule
.Untuk dukungan Soket, tambahkan panggilan ke
AfxNetInitModule
DLL MFC reguler Anda diCWinApp::InitInstance
.
Rilis build DLL dan aplikasi MFC tidak menggunakan DLL terpisah untuk dukungan database, soket, atau OLE. Namun, aman untuk memanggil fungsi inisialisasi ini dalam mode rilis.
Objek CDynLinkLibrary
Selama setiap operasi yang disebutkan di awal artikel ini, MFC perlu mencari nilai atau objek tertentu. Misalnya, selama deserialisasi, MFC perlu mencari semua kelas run-time yang saat ini tersedia untuk mencocokkan objek dalam arsip dengan kelas run-time yang tepat.
Sebagai bagian dari pencarian ini, MFC memindai semua DLL ekstensi MFC yang digunakan dengan menjalankan rantai CDynLinkLibrary
objek. CDynLinkLibrary
objek melekat secara otomatis ke rantai selama konstruksinya dan dibuat oleh setiap DLL ekstensi MFC pada gilirannya selama inisialisasi. Setiap modul (aplikasi atau DLL MFC reguler) memiliki rantai CDynLinkLibrary
objeknya sendiri.
Agar DLL ekstensi MFC tersambung ke rantai CDynLinkLibrary
, dll harus membuat CDynLinkLibrary
objek dalam konteks setiap modul yang menggunakan DLL ekstensi MFC. Untuk menggunakan DLL ekstensi MFC di DLL MFC reguler, DLL ekstensi harus menyediakan fungsi inisialisasi CDynLinkLibrary
yang diekspor yang membuat objek. Setiap DLL MFC reguler yang menggunakan DLL ekstensi MFC harus memanggil fungsi inisialisasi yang diekspor.
Jika Anda hanya akan menggunakan DLL ekstensi MFC dari aplikasi MFC, dan tidak pernah dari DLL MFC biasa, maka cukup untuk membuat CDynLinkLibrary
objek dalam fungsi DLL DllMain
ekstensi MFC. Inilah yang dilakukan kode DLL ekstensi MFC DLL MFC. Saat memuat DLL ekstensi MFC secara implisit, DllMain
memuat dan menjalankan sebelum aplikasi dimulai. Setiap CDynLinkLibrary
kreasi dikabeli ke dalam rantai default yang disediakan DLL MFC untuk aplikasi MFC.
Adalah ide yang buruk untuk memiliki beberapa CDynLinkLibrary
objek dari satu DLL ekstensi MFC dalam satu rantai apa pun. Ini terutama benar jika DLL ekstensi MFC mungkin dibongkar secara dinamis dari memori. Jangan panggil fungsi inisialisasi lebih dari sekali dari satu modul.
Kode Sampel
Kode sampel ini mengasumsikan bahwa DLL MFC reguler secara implisit menautkan ke DLL ekstensi MFC. Untuk menautkan secara implisit, tautkan ke pustaka impor (file LIB) dll ekstensi MFC saat Anda membangun DLL MFC reguler.
Baris berikut harus berada di sumber DLL ekstensi MFC:
// YourExtDLL.cpp:
// standard MFC extension DLL routines
#include "afxdllx.h"
static AFX_EXTENSION_MODULE extensionDLL;
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// MFC extension DLL one-time initialization
if (!AfxInitExtensionModule(extensionDLL, hInstance))
return 0;
}
return 1; // ok
}
// Exported DLL initialization is run in context of
// application or regular MFC DLL
extern "C" void WINAPI InitYourExtDLL()
{
// create a new CDynLinkLibrary for this app
new CDynLinkLibrary(extensionDLL);
// add other initialization here
}
Pastikan untuk mengekspor fungsi InitYourExtDLL . Anda dapat menggunakan __declspec(dllexport)
, atau mengekspornya dalam file DEF untuk DLL Anda, seperti yang ditunjukkan di sini:
// YourExtDLL.Def:
LIBRARY YOUREXTDLL
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD SINGLE
EXPORTS
InitYourExtDLL
Tambahkan panggilan ke InitInstance
anggota CWinApp
objek -turunan di setiap DLL MFC reguler menggunakan DLL ekstensi MFC:
// YourRegularDLL.cpp:
class CYourRegularDLL : public CWinApp
{
public:
virtual BOOL InitInstance(); // Initialization
virtual int ExitInstance(); // Termination
// nothing special for the constructor
CYourRegularDLL(LPCTSTR pszAppName) : CWinApp(pszAppName) { }
};
BOOL CYourRegularDLL::InitInstance()
{
// any DLL initialization goes here
TRACE0("YOUR regular MFC DLL initializing\n");
// wire any MFC extension DLLs into CDynLinkLibrary chain
InitYourExtDLL();
return TRUE;
}