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
| Вернуться в корень Архива
|