Я завершаю расширение DLL MFC (MFCXDLL_2), чтобы сделать его функциональность доступной для программистов на C #.
Оболочка - это «Обычная DLL, использующая разделяемую MFC DLL» с «Common Language Runtime Support (/ clr»).)».(Смешанный режим).
Классы в MFCXDLL_2, которые должны быть доступны, оформлены в MFCXDLL_3.
Сценарий, который я наблюдаю, - это случай, когда MFCXDLL_2 используется из пользовательского элемента управления C # .NET, работающего в собственном приложении.
Другая библиотека расширения MFC - MFCXDLL_1 - внутри собственного приложения также использует MFCXDLL_2, и это вызывает проблемы.
Когда я запускаю собственное приложение, оно неявно загружает MFCXDLL_2.
Когда я загружаю пользовательский элемент управления .NET, тот же самый MFCXDLL_2 загружается снова явно в соответствии с рекомендациями в http://msdn.microsoft.com/en-us/library/ksa99t88.aspx, «Использование библиотек базы данных, OLE и расширений сокетов в обычных DLL».
И собственный код, и пользовательский элемент управления .NET создают один и тот же тип класса и вызывают один и тот же метод в MFCXDLL_2.
Метод десериализует данные (полученные из общей памяти) и возвращает деСериализованные данные для абонента.Это прекрасно работает из собственного кода, пока я не загружу пользовательский элемент управления .NET.
После загрузки пользовательского элемента управления .NET десериализация перестает работать из собственного кода, но прекрасно работает при вызове из пользовательского элемента управления .NET.
Я подключил WinDbg к отладочной версии собственного приложения и запустил свой сценарий.Во время десериализации WinDbg обнаружил следующее:
«Предупреждение: загрузка из архива невозможна.Класс не определен.Исключение CArchive: badClass. ”
Я думаю, что здесь есть некоторые проблемы с ресурсами, поэтому я запускаю версию выпуска собственного приложения, загружая версию MFCXDLL_2.Затем я загружаю отладочную версию пользовательского элемента управления .NET, которая снова загружает отладочную версию MFCXDLL_2 - в собственное приложение.
Тогда все просто отлично работает.Одна версия выпуска MFCXDLL_2, загруженная собственным кодом, и одна отладочная версия MFCXDLL_2, загруженная пользовательским элементом управления .NET - все выполняется внутри собственного приложения.
Так что происходит?Разве невозможно получить доступ к одному и тому же MFCXDLL, например, из библиотеки DLL расширения и из обычной библиотеки DLL одновременно в одном приложении?
Разрушена ли цепочка ресурсов каким-либо образом?Каковы возможные решения?
Вот некоторый код, показывающий, как загружается DLL MFCXDLL_2
Когда собственное приложение запускается MFCXDLL_2 DLLMain вызывается:
static AFX_EXTENSION_MODULE MFCXDLL_2 = { NULL, NULL };
static CDynLinkLibrary* gpDynLinkLibrary = NULL;
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID )
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// Extension DLL one-time initialization
AfxInitExtensionModule(MFCXDLL_2, hInstance);
// Insert this DLL into the resource chain
gpDynLinkLibrary = new CDynLinkLibrary(MFCXDLL_2);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
if (gpDynLinkLibrary)
{
delete gpDynLinkLibrary;
gpDynLinkLibrary = NULL;
}
// Terminate the library before destructors are called
AfxTermExtensionModule(MFCXDLL_2);
}
return 1; // ok
}
Когда загружается пользовательский элемент управления .NET, MFCXDLL_2 DLL загружается снова:
//==============================================================
// Exported DLL initialization to run in context of Regular DLL.
// Must be called in InitInstance
// BOOL CYourRegularDLLApp::InitInstance()
//==============================================================
extern "C" _declspec(dllexport) CDynLinkLibrary* WINAPI InitMFCXDLL_2FromRegularDLL()
{
if (gpDynLinkLibrary)
{
delete gpDynLinkLibrary;
gpDynLinkLibrary = NULL;
}
// Create a new CDynLinkLibrary for this Regular DLL
return new CDynLinkLibrary(MFCXDLL_2);
}
Десериализованный код внутри MFCXDLL_2
CMyClass* pMyclass = NULL; //CObject derived serializeable class
BYTE *pBuf = pGlobalCom->GetBuffer(); //Buffer with serialized CMyClass
int nBufSize = pGlobalCom->GetSize(); //Size of buffer
CMemFile mf;
mf.Attach(pBuf,nBufSize);
CArchive ar(&mf, CArchive::load); //“Warning: Cannot load CMyClass from archive. Class not defined.CArchive exception: badClass.”
ar >> pMyclass; //CArchive exception thrown
ar.Close();
mf.Detach();
На рисунке показана взаимосвязь между dll.