嘗試的環境大概是這樣的,MFC常規DLL,以及普通的控制臺程序。
MFC常規DLL的一個導出函數
1
__declspec( dllexport ) void create_frm2()
2

{
3
CFileDialog dlg( TRUE );
4
dlg.DoModal();
5
}

2



3

4

5

調用導出函數的應用程序
1
int _tmain(int argc, _TCHAR* argv[])
2

{
3
create_frm2();
4
5
return 0;
6
}

2



3

4

5

6

不過在嘗試的過程中,出了點問題,在調用導出函數的時候不是崩潰就是大量的DEBUG ASSERT,看起來卡在CFileDialog的構造函數上了。
請教同事,才知道大概緣由。
在MFC常規DLL自帶的DllMain函數中,有這么一些細節,在下面的中文注釋中標注
1
extern "C"
2
BOOL WINAPI InternalDllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /**//*lpReserved*/)
3

{
4
if (dwReason == DLL_PROCESS_ATTACH)
5
{
6

7
8
_AFX_THREAD_STATE* pState = AfxGetThreadState();
9
//下面這句,保存了前一個模塊的module state。
10
//但是如果前一個模塊是非MFC程序,那么pPrevModState=0
11
AFX_MODULE_STATE* pPrevModState = pState->m_pPrevModuleState;
12
13

14
15
// initialize the single instance DLL
16
CWinApp* pApp; pApp = AfxGetApp();
17
if (pApp != NULL && !pApp->InitInstance())
18
{
19
pApp->ExitInstance();
20
AfxWinTerm();
21
goto Cleanup; // Init Failed
22
}
23
24

25
26
bResult = TRUE;
27
28
Cleanup:
29
pState->m_pPrevModuleState = pPrevModState;
30
#ifdef _AFXDLL
31
// restore previously-saved module state
32
//這里,在退出DllMain前,將module state的指針設置為0
33
//以后AfxGetModuleState的值就是0了
34
//這樣的情況下,MFC的很多方法和類根本無法使用
35
VERIFY(AfxSetModuleState(AfxGetThreadState()->m_pPrevModuleState) ==
36
&afxModuleState);
37
DEBUG_ONLY(AfxGetThreadState()->m_pPrevModuleState = NULL);
38
#endif
39
return bResult;
40
}
41
42

43
44
return TRUE;
45
}

2


3



4

5



6


7

8

9

10

11

12

13


14

15

16

17

18



19

20

21

22

23

24


25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42


43

44

45

由于我的調用程序不是MFC程序,所以MFC常規DLL中保存的module state值為0,當構造CFileDialog時,相關的地方就失敗了。
知道原因,就知道解決方法了。
1.注意到DllMain恢復前一個module state的代碼,是寫在 #ifdef _AFXDLL里面的。也就是說,取消_AFXDLL的宏定義,module state的值就應該是有效的。
我將MFC常規DLL的編譯選項Use Of MFC 改為 Use MFC In a Static Library后重新編譯,執行正常。
2.第二個方法就是想辦法設置一個module state,比如可以用MFC常規DLL中的那個module state
1
BOOL Capp3App::InitInstance()
2

{
3
CWinApp::InitInstance();
4
5
//在MFC DLL中保存module state
6
g_ms = AfxGetModuleState();
7
8
return TRUE;
9
}
10
11
12
__declspec( dllexport ) void create_frm2()
13

{
14
//剛進來,這時候module state = 0
15
//將它設置為一個有效值
16
AfxSetModuleState( g_ms );
17
18
CFileDialog dlg( TRUE );
19
dlg.DoModal();
20
}

2



3

4

5

6

7

8

9

10

11

12

13



14

15

16

17

18

19

20

3.第三個方法就是,把調用程序換成MFC程序,不過我不是很喜歡這樣