Extension DLLs, COM, and resources
Edward N. -- ens@edisun.cb.att.com Tuesday, October 01, 1996 Environment: VC++ 4.2, NT 4.0 The abstract: 1. DLL's loaded as a result of CoCreateInstance take a different initialization path than DLL's implicitly loaded. 2. Only the implicitly loaded DLL's have CDynLinkLIbraries in the linked list searched by AfxFindResourceHandle. 3. I need the mfc application to find a resource in my COM loaded DLL. What incantation do I need to make to get my View DLL in the "correct" linked list. The story: I am having a problem that is often discussed - resources in my DLL are not being found by the application. The offered solution: HINSTANCE hOldRes = AfxGetResourceHandle(); AfxSetResourceHandle(hInst_DLL); CMyDialog dlg; dlg.DoModal(); AfxSetResourceHandle(hOldRes); won't work. In my case, the DLL holds an implementation of a CFormView derived class. At runtime, my MFC document/view application: 1, determines what view it will need, 2. dynamically loads the mfc extension DLL implementing it (more on that later), 3. calls a function in the DLL to get the view's CRuntimeClass pointer, (pViewClass) 4. creates a CSingleDocTemplate pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME, RUNTIME_CLASS(CMyDoc), RUNTIME_CLASS(CMainFrame), pViewClass); 5. Later, the pDocTemplate's magic happens and the document, mainframe and (alas not) view are created. CFormView's constructor fails looking up its resources (via a call to _AfxCheckDialogTemplate. It turns out, _AfxCheckDialogTemplate uses AfxFindResourceHandle, which is looking in the WRONG linked list of CDynLinkLibrarys (I've identified 4 of them in my app while single stepping through initialization) The problem with the previous offered solution is it assumes I own the code that makes the call that looks up resources. I am not making the call, and I doubt that wrapping CMyApp::ProcessShellCommand in AfxSetResourceHandle calls would work (though admittedly I haven't tried). At this point you may be wondering how I get the view's CRuntimeClass pointer. Well, I could have exported a well known function for the application to call, but I did it the new improved COM way; the extension DLL also implements an object providing a COM interface, IViewManager, that the application can get via CoCreateInstance. This has 2 benefits: 1. I have a well defined interface for view developers to implement for negotiation twixt the application and the view. 2. When CoCreateInstance loads the InProc32 server for MyView.Manager.1, it has the side-effect of loading the DLL for my view (since they are one-in-the-same). In single stepping from startup through the failed assertion, I have seen 3 different DllMain functions called (from DLLINIT.CPP, DLLMODUL.cpp and DLLOLE.cpp). DLINIT's and DLLOLE's DllMain both create new CDynLinkLibraries that go into the list maintained by the AFX_MODULE_STATE returned by AfxGetModuleState's "else clause", i.e. it returns _afxBaseModule.GetData(). This is the list searched by AfxFindResourceHandle. (although, in AfxFindResourceHandle's call to AfxGetModuleState, it's the _afxThreadState's m_pModuleState->m_ModuleState in the "if clause" that coughs it up) 1. How can I get my DLL's CDynLinkLibrary into the "correct" list? 2. Since this (these?) list(s) exist, why is the oft mentioned AfxSetResourceHandle solution necessary in the first place. 3. Isn't it time resources were handled a bit more robustly? Imagine life where resources are dealt with as smoothly as function calls. Ed Schiebel AT&T Network & Computing Services e.n.schiebel@att.com
Kyle Herbert -- kyleh@ckeng.com Thursday, October 03, 1996 Environment: VC++ 4.2, NT 4.0 Edward, It sounds to me like you and I are banging our heads against the same wall! Though I'm not using the Document/View architecture, I too am trying to load DLL resources dynamically based upon a user's instructions. Your research was very thorough and served to answer a number of my questions (my hat's off to you). I was running into the same issue wherein the dialog template could not be located within the client's resource chain. AFX_MANAGE_STATE and AfxGetResourceHandle provided relief for me only when the client was not actively managing the object created in the DLL. Essentially, I decided that I needed an MFC extension DLL that could be explicitly linked. An individual responded to my posting concerning this, saying that there was nothing preventing an MFC extension DLL from being explicitly linked. This intrigued me as I had not found documentation to support this. I immediately thought of your point #2: >2. Only the implicitly loaded DLL's have CDynLinkLIbraries in the linked >list searched by AfxFindResourceHandle. On a whim, I created an MFC extension DLL, added to it my objects (property pages), and also added a "well-known" C dllexport interface. My main application acquires and modifies the DLL objects via the C interface. I do not specify the library file in the linker settings, nor do I include in the main application the class definition header files for the DLL objects. I use LoadLibrary to dynamically attach to the DLL. Because the MFC extension DLL uses CDynLinkLibrary, the resources appear to be inserted properly into the client's resource chain. Using the C interface, I create my property page objects and add them to the client's property sheet. The client then handles viewing the property sheet and its associated pages. I have only implemented and begun testing this today. However, thus far the results have been very promising. I have not encountered an assertion failure of any kind yet. If your application is such that you can create the DLL's objects in a C dllexport function and "hand them off" to the client application, I would encourage you to give this a try and we'll compare notes. If my explanation is poor, let me know and I'll send you some source code. I second your last comment: >3. Isn't it time resources were handled a bit more robustly? Imagine life >where resources are dealt with as smoothly as function calls. --Kyle Kyle Herbert "My mind is aglow with whirling, CK Engineering transient nodes of thought, careening http://www.ckeng.com through a cosmic whirl of invention." kyleh@ckeng.com ---Blazing Saddles
| Вернуться в корень Архива |