I am wrapping up an MFC extension DLL (MFCXDLL_2) to make its functionality available for C# programmers.
The wrapper is a “Regular DLL using shared MFC DLL” with “Common Language Runtime Support (/clr)”. (Mixed mode).
The classes in MFCXDLL_2 that shall be available are decorated in MFCXDLL_3.
The scenario I am experiencing is the case where MFCXDLL_2 is used from a C# .NET user control running in a native application.
Another MFC Extension DLL -MFCXDLL_1-inside the native application also uses the MFCXDLL_2 and this cause trouble.
When I start the native application it will implicitly load the MFCXDLL_2.
When I load the .NET user control, the same MFCXDLL_2 is loaded again explicitly according to the advice in http://msdn.microsoft.com/en-us/library/ksa99t88.aspx, “Using Database, OLE, and Sockets Extension DLLs in Regular DLLs”.
Both the native code and the .NET user control instantiate the same class type and call the same method in the MFCXDLL_2.
The method de-serializes data (received over shared memory) and returns the de-serialized data to the caller. This works great from native code until I load the .NET user control.
After loading the .NET user control, de-serializing stops working from native code but it works great when called from the .NET user control.
I attached WinDbg to the debug version of the native application and run my scenario. WinDbg found as follows during de-serialization:
“Warning: Cannot load from archive. Class not defined. CArchive exception: badClass.”
I think there are some resource issues here so I run the release version of the native application loading the release version of MFCXDLL_2. Then I load the debug version of the .NET user control –which again loads the debug version of MFCXDLL_2- into the native application.
Then everything just works great. One release version of the MFCXDLL_2 loaded by the native code and one debug version of MFCXDLL_2 loaded by the .NET user control –all running inside the native application.
So what is happening? Is it not possible to access the same MFCXDLL from e.g. an extension DLL and a regular DLL at the same time in the same application?
Is the resource chain destroyed in some way?
What are the possible solutions?
Here is some code showing how the MFCXDLL_2 DLL is loaded
When the native application starts MFCXDLL_2 DLLMain is called:
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
}
When the .NET user control is loaded, the MFCXDLL_2 DLL is loaded again:
//==============================================================
// 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);
}
The deserialize code inside 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();
The image show the relationship between the dlls.