0=*'^=@>6(65?VP=Q]#TAP"H*A4L)X'#_T\0]4MUE*[#9
MD6("+7$I,?^]8C!QW'(!D/&A): #@=.G]^JVP#B!X6<7,,00`R A=/\MDFLR
MVD+3QMUR"< ZD"T!_]_QZ6%RUMB[R;*B%O+CQ-/_0`(I3R\#?K[ 10.#R8R/E@&P=,!M@OR "@^,'!.2QP0,#6!6-!?7W!287>JAONZ(&)R>59E
M"[8FL2+A@V# 250N3T)*#1\.+\L/-U9E7ZJ%0#$)4!"U_Q&/$I4,OQ.O5F4W
MD*R +X)S#T%"$# V#[\6[Q(Z.[MTP2\!9!$JN?&ZDF/Q]$]R /_7 _K$@YL&NA<3"&\/^@$&GZ+A#C,&%RN##?L FB3]G NC!*
M0*GD7%QT4$2<158M48#@+5!34H#P_^JVV\%PD,["QM*M\#WQ7@'_/-$[(#/"
ME8^6E]OQ"[7 T'_+=JU3B2+9XC@A8@&[T4WX3T15B^#,<:N#B02Z(/^.8-H&
MP[-\\=US: "MT/-!?U9EBE%H`7(!HA +L([V+^\Z'SLO/#\]3R\YJSH!O*8_
MJH=PI<)85F6[,JR!(D,QSB9"3T^[\(-105 S89"JA2A(@V"5$4Y#/0,@:)I@
MY2''\<_P1%?H3U)$SW!WD(#$(*WP@<_P3%!63TE$E_JQ1ZTO*FP<@#=1Y?X+DK0_59F?4&?0PLPI.TN?0P0H0V3 \!QZ9BE.
M'T^W(#U'#YA4)O\*H]#?_]'B,Y2TYHDB-JHWBSE2.+3_I!9,#T-TD9%97UIO1F%4
M[_]KCVPX3]]0[U'_4P]4$6J/?W*_;(]4HE9 : MMMEPE3)E?!2)(I)#,LB)+
MI)#_8!'\$L:4DK+LL 3P\2&E4O^8\-O W:&@-P2&R."NH;VQ^[Q!'$!7[+#0
M5(XQ'(,T\?_:48'BL7,TZB[4=T+'1H+3_%@N*A',LHXB?5FC0*"QOWX>Y"*L
M\36VX<>_C,;O2N=WB5"DUI GE\>'OR-#Z8*UQ7SA'I)#JMN/1[]^@
MT["4$<#00Z[2]?'4<'HAF5PMB_AG\,[2U0!F_S P\6"Z,.6AB_F.;XOVF5S\
M3TM?\9=D8 +\4:R!L7/]\ (_*^&?T\_P@@+ZU:#8_^6%GF?M4#F'ZK8!0"UP
MSW#^:7FD7% $8.5 NU&MTS!Q[YB!]U'3QF5S* 9!P5"E4F_QT-.BJ\;7A2&&
MT-(L8O^6]*46(W#ZH0&R-H'Q@@(_OS;QEU#UHJ*#7+B[/&(*\?T%\6>E8<]1
MR- $8 'BTATV4 : Q#!B-A#W8B)B[V[ V_'B4(FB::\`+^'^T*,))DY23:
ML3*Q?]M!KO*#4Q$6"9"T4[#E9?_LH-K T%/9P&_I8K7;\::F_[3"
MB8)<)=UR>B%A(_[3T4+]\@%F;L"XXV 0X]&T)BL!_S=1^J&RU/.OWS+D80F1
MP[/^;36CN1/<@!3 !& +(.EQ_^LARA'ZQ;V?OJ7;\>U0FE#_\S+;L\,CLP2Y
MT[YT\L'B8/^NL*-DP<_TOO]NCV_2EHS$=]0"-_#G0'D<0$.PIE!P__H!!&!]
M5>0B_6#?P0KQGO_?+N)<)?U@,!/$$V*C8I0*>$,K*WNSJUY7A30
M,D!MMG.*_3#14][N?>#4R&* WP;?__?!>/O
MY/_8A/=0=HK1_]D^1%C>!6VV2W!V':CFV,'_E/#\(111^>+!8S1"U?/V(=\V
M@+91P'$_A"9Q9B] ^?#_F&(NXIH38Q@O53?1WS,*H/N0X ?-1)UR:D !L K0
M)?$OG?.>3_(<%UG?8 LT),0NQ%";_IHW\!NR*__OP#/`=_*
M%N_]S7.NB>"L<6-?8*K!(W'5RY!'#%!(I$9H@@$<0 `K-#D@,C(X(( V-" X
M," U%5"?.-7.$1"TU
MT#,S-#
Ranjiv Sharma -- RanjivS@datastorm.com
Wednesday, May 01, 1996
The only time you do not have to use your dll_instance_switcher class is
if you do not have any resource ID's that are same in any of the
extension DLL's that are being linked to the MFC App. This is really a
problem, since the resource editor ends up using the same ID's for
dialogs in different DLL's (starts with 101 for dialogs). Since it is a
pain to keep track of unique resource ID's - especially if more than one
person is working on a project, it is best to always use your
dll_instance_switch class.
The MFC solution may have been slightly more acceptable, if the
resource chain always started with the Resource of the module in which
the function was being executed, and then, if the resource was not found,
to go through the other modules in the chain. The current implementation
only leads to great confusion, when you have dialog boxes from other
dll's coming up - or the wrong strings being loaded.
In order to keep the same programming model for extension and non
extension DLL's (which is what is desirable), you could define a macro
something like this
#ifdef _AFXEXT
#define SWITCH_RESOURCE dll_instance_switcher
#else //_USRDLL
#define SWITCH_RESOURCE AFX_MANAGE_STATE(AfxGetStaticModuleState())
Now you can do the same thing in every exported function in your dll
ExportedFuntion()
{
SWITCH_RESOURCE;
....
}
-Ranjiv
(ranjivs@datastorm.com)
----------
From: owner-mfc-l[SMTP:owner-mfc-l@netcom.com]
Sent: Monday, April 29, 1996 9:41 PM
To: 'mfc-l@netcom.com'; 'mattes@logotec.com'
Subject: RE: AFXEXT: complete Soap Opera
You're solution is a good one. Your discoveries are "by design". The
module state for an extension DLL is the same as the .EXE since there is
no CWinApp object in an Extension DLL. Your resources will be found if
you have properly hooked up the CDynlinklibrary object and you don't have
any conflicting resource IDs in other modules (.EXE and .DLLs). So
normally, there isn't a need to call AfxSetResourceHandle(). But if you
want to call AfxSetResourceHandle() to be explicit about which module has
the resource that is perfectly fine.
--dan
----------
From: Matthias Bohlen[SMTP:mattes@logotec.com]
Sent: Tuesday, April 23, 1996 9:39 AM
To: mfc-l@netcom.com
Subject: AFXEXT: complete Soap Opera
Hello,
two weeks ago, I started a thread here about linking problems with
AFX extension DLL's. I have received responses from many people but
the problem still remains. To put things absolutely clear, I re-state
it with complete info (sorry for the extreme length of this mail
message, but the MS guys seem to have a problem there).
-------------- List of facts starts here -------------------------
A) I use Visual C++ 4.0. I write an EXE program with several
MFC extension DLL's (_AFXEXT, _AFXDLL, _WINDLL defined).
B) My problem is: I want to access resources inside the *.RES file that
is linked to an extension DLL.
C) Microsoft offers two solutions:
C.1) call AfgxSetResourceHandle( hExtensionDLL ) (that works!)
C.2) call AFX_MANAGE_STATE( AfxGetStaticModuleState() ) (that does
NOT work!)
D) In "DLLs: Building and Using an Extension DLL", Microsoft states
that I have to think about the following to have a correct MFC extension
DLL:
" * It does not have a CWinApp-derived object.
* It calls AfxInitExtensionModule in its DllMain function. The
return value of this function should be checked. If a zero value is
returned from AfxInitExtensionModule, return 0 from your DllMain
function.
* It will create a CDynLinkLibrary object during
initialization if the extension DLL wishes to export CRuntimeClass
objects or resources to the application. * For an example of a DLL
that fulfills the basic requirements of an extension DLL, see the MFC
Advanced Concepts sample DLLHUSK. In particular, look at the
TESTDLL1.CPP and TESTDLL2.CPP files."
Found out: to do this, you have to #include "afxdllx.h".
E) In "Managing the State Data of MFC Modules", Microsoft states
that:
A module's state data is contained in a structure, and is always via a
pointer to that structure. When the flow of execution enters a
particular module (as shown in Figure 2), that module's state must be
the "current" or "effective" state. Therefore, each thread object has
a pointer to the effective state structure of that application.
Keeping this pointer updated at all times is vital to managing the
application's global state and maintaining the integrity of each
module's state. Incorrect management of the global state can lead to
unpredictable application behaviour."
F) Statement E) told me that AFX_MANAGE_STATE would be absolutely
necessary. Therefor, I chose to take Step C.2.
G) Step C.2 caused linker errors about multiply defined symbols:
mfcs40d.lib(dllmodul.obj) : error LNK2005: __pRawDllMain already
defined in DLLINIT.OBJ mfcs40d.lib(dllmodul.obj) : error LNK2005:
_DllMain@12 already defined in DLLINIT.OBJ
mfcs40d.lib(dllmodul.obj) :
warning LNK4006: __pRawDllMain already defined in DLLINIT.OBJ; second
definition ignored
mfcs40d.lib(dllmodul.obj) : warning LNK4006:
_DllMain@12 already defined in DLLINIT.OBJ; second definition ignored
H) To track the problem down, I browsed a little in \MSDEV\MFC\SRC
and found the only place where AfxGetStaticModuleState() is defined.
This file is called DLLMODUL.CPP. The file also contains these
interesting
lines of code:
//////////////////////////////////////////////////////////////////////
////// // export DllMain for the DLL
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID
/*lpReserved*/)
{
...
}
extern "C" BOOL WINAPI RawDllMain(HINSTANCE, DWORD dwReason, LPVOID);
extern "C" BOOL (WINAPI* _pRawDllMain)(HINSTANCE, DWORD, LPVOID) =
&RawDllMain;
extern "C"
BOOL WINAPI RawDllMain(HINSTANCE, DWORD dwReason, LPVOID)
{
...
}
K) From Step "D", we know that I had to #include "afxdllx.h". This
file contains the interesting code lines:
extern "C" BOOL WINAPI ExtRawDllMain(HINSTANCE, DWORD dwReason,
LPVOID);
extern "C" BOOL (WINAPI* _pRawDllMain)(HINSTANCE, DWORD,
LPVOID) = &ExtRawDllMain;
L) From "H" and "K" we can see that we need not wonder about the
name clashes: We have two pRawDLLMain's (from DLLMODUL.CPP and from
AFXDLLX.H) and two DLLMain's (one from DLLMODUL.CPP, the other from
my own DLL initialization module). The linker messages from Step "G"
are logical. Check mate!
----------- End of fact list ------------------------------------
OK, what do we learn from this? I think, one of the following must be
true:
a) MS did not pay attention when writing the code (I cannot imagine
that!).
b) MS does not want me to call AFX_MANAGE_STATE inside an MFC
extension DLL but forgot to say that.
Possibility "b" is more likely because in "TN058: MFC Module State
Implementation", Microsoft states:
"Note that certain kinds of DLLs, specifically "MFC Extension" DLLs
don't switch the module state in their RawDllMain (actually, they
usually don't even have a RawDllMain). This is because they are
intended to behave "as if" they were actually present in the
application that uses them. They are very much a part of the
application that is running and it is their intention to modify that
application's global state."
----------
End of the story: I kept my DLLMain, threw out AFX_MANAGE_STATE and
replaced it by the following C++ class:
extern AFX_EXTENSION_MODULE LOGOCADDLL;
class dll_instance_switcher
{
public:
dll_instance_switcher()
{
m_hinst = AfxGetResourceHandle();
AfxSetResourceHandle (LOGOCADDLL.hResource);
}
~dll_instance_switcher()
{
AfxSetResourceHandle (m_hinst);
}
private:
HINSTANCE m_hinst;
};
I put an object of this class into every exported function and I can
find the resources OK.
Does somebody want to comment?
Bye...
Matthias Bohlen
-------------------------------------------------------
Matthias Bohlen Logotec Software GmbH
Phone: +49 228 64 80 520 Chateauneufstr. 10
FAX: +49 228 64 80 525 D-53347 Alfter, Germany
E-mail: mattes@logotec.com
-------------------------------------------------------
Mike Blaszczak -- mikeblas@msn.com
Friday, May 03, 1996
----------
From: owner-mfc-l@netcom.com on behalf of Ranjiv Sharma
Sent: Wednesday, May 01, 1996 09:33
> The only time you do not have to use your dll_instance_switcher class is
> if you do not have any resource ID's that are same in any of the
> extension DLL's that are being linked to the MFC App.
This is not true. It is _not_ necessary to manually manage the module state
when the call is coming from another MFC AFXDLL-compiled module. I outlined
these rules in my previous note on this subject. By insulating every entry
point in your DLL with a class like the one in question, you'll can make a
significant adverse effect on performance!
.B ekiM
TCHAR sz[] = _T("How's your Bud Ice? Doo be doo be do...");
| Вернуться в корень Архива
|