to rivershan(笨猫)(C++/VC初学者) : Regular DLL using Shared MFC DLL
to rivershan(笨猫)(C++/VC初学者) : 我刚试过,用Regular DLL with MFC staticlly linked也不行
to shinespring(shine): 试过了,不行呀!
int ShowDlg() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CCMyDlg m_MyDlg; m_MyDlg.DoModal(); return 0; }去掉m_MyDlg这个全局变量,或者你用指针
请问aprilsnow? 解决了没有呀? 我也遇到相同的问题了
See the comment below, FYI :MFC DLLs—Extension vs. Regular We've been looking at Win32 DLLs that have a DllMain function and some exported functions. Now we'll move into the world of the MFC application framework, which adds its own support layer on top of the Win32 basics. AppWizard lets you build two kinds of DLLs with MFC library support: extension DLLs and regular DLLs. You must understand the differences between these two types before you decide which one is best for your needs. Of course, Visual C++ lets you build a pure Win32 DLL without the MFC library, just as it lets you build a Windows program without the MFC library. This is an MFC-oriented book, however, so we'll ignore the Win32 option here.An extension DLL supports a C++ interface. In other words, the DLL can export whole classes and the client can construct objects of those classes or derive classes from them. An extension DLL dynamically links to the code in the DLL version of the MFC library. Therefore, an extension DLL requires that your client program be dynamically linked to the MFC library (the AppWizard default) and that both the client program and the extension DLL be synchronized to the same version of the MFC DLLs (mfc42.dll, mfc42d.dll, and so on). Extension DLLs are quite small; you can build a simple extension DLL with a size of 10 KB, which loads quickly. If you need a DLL that can be loaded by any Win32 programming environment (including Visual Basic version 6.0), you should use a regular DLL. A big restriction here is that the regular DLL can export only C-style functions. It can't export C++ classes, member functions, or overloaded functions because every C++ compiler has its own method of decorating names. You can, however, use C++ classes (and MFC library classes, in particular) inside your regular DLL. When you build an MFC regular DLL, you can choose to statically link or dynamically link to the MFC library. If you choose static linking, your DLL will include a copy of all the MFC library code it needs and will thus be self-contained. A typical Release-build statically linked regular DLL is about 144 KB in size. If you choose dynamic linking, the size drops to about 17 KB but you'll have to ensure that the proper MFC DLLs are present on the target machine. That's no problem if the client program is already dynamically linked to the same version of the MFC library. When you tell AppWizard what kind of DLL or EXE you want, compiler #define constants are set as shown in the following table. Dynamically Linked to Shared MFC Library Statically Linked* to MFC Library Regular DLL _AFXDLL, _USRDLL _USRDLL Extension DLL _AFXEXT, _AFXDLL unsupported option Client EXE _AFXDLL no constants defined * Visual C++ Learning Edition does not support the static linking option. If you look inside the MFC source code and header files, you'll see a ton of #ifdef statements for these constants. This means that the library code is compiled quite differently depending on the kind of project you're producing. The Shared MFC DLLs and the Windows DLLs If you build a Windows Debug target with the shared MFC DLL option, your program is dynamically linked to one or more of these (ANSI) MFC DLLs: mfc42d.dll Core MFC classes mfco42d.dll ActiveX (OLE) classes mfcd42d.dll Database classes (ODBC and DAO) mfcn42d.dll Winsock, WinInet classes When you build a Release target, your program is dynamically linked to mfc42.dll only. Linkage to these MFC DLLs is implicit via import libraries. You might assume implicit linkage to the ActiveX and ODBC DLLs in Windows, in which case you would expect all these DLLs to be linked to your Release-build client when it loads, regardless of whether it uses ActiveX or ODBC features. However, this is not what happens. Through some creative thunking, MFC loads the ActiveX and ODBC DLLs explicitly (by calling LoadLibrary) when one of their functions is first called. Your client application thus loads only the DLLs it needs. MFC Extension DLLs—Exporting Classes If your extension DLL contains only exported C++ classes, you'll have an easy time building and using it. The steps for building the EX22A example show you how to tell AppWizard that you're building an extension DLL skeleton. That skeleton has only the DllMain function. You simply add your own C++ classes to the project. There's only one special thing you must do. You must add the macro AFX_EXT_CLASS to the class declaration, as shown here: class AFX_EXT_CLASS CStudent : public CObject This modification goes into the H file that's part of the DLL project, and it also goes into the H file that client programs use. In other words, the H files are exactly the same for both client and DLL. The macro generates different code depending on the situation—it exports the class in the DLL and imports the class in the client. The MFC Extension DLL Resource Search Sequence If you build a dynamically linked MFC client application, many of the MFC library's standard resources (error message strings, print preview dialog templates, and so on) are stored in the MFC DLLs (mfc42.dll, mfco42.dll, and so on), but your application has its own resources too. When you call an MFC function such as CString::LoadString or CBitmap::LoadBitmap, the framework steps in and searches first the EXE file's resources and then the MFC DLL's resources. If your program includes an extension DLL and your EXE needs a resource, the search sequence is first the EXE file, then the extension DLL, and then the MFC DLLs. If you have a string resource ID, for example, that is unique among all resources, the MFC library will find it. If you have duplicate string IDs in your EXE file and your extension DLL file, the MFC library loads the string in the EXE file. If the extension DLL loads a resource, the sequence is first the extension DLL, then the MFC DLLs, and then the EXE. You can change the search sequence if you need to. Suppose you want your EXE code to search the extension DLL's resources first. Use code such as this: HINSTANCE hInstResourceClient = AfxGetResourceHandle(); // Use DLL's instance handle AfxSetResourceHandle(::GetModuleHandle("mydllname.dll")); CString strRes; strRes.LoadString(IDS_MYSTRING); // Restore client's instance handle AfxSetResourceHandle(hInstResourceClient);You can't use AfxGetInstanceHandle instead of ::GetModuleHandle. In an extension DLL, AfxGetInstanceHandle returns the EXE's instance handle, not the DLL's handle.
1、在向导中点MFC AppWizard(dll),生成一个支持MFC的DLL。
2、在DLL中添加一个对话框资源。
3、给对话框对应一个类m_MyDlg。
4、在CXXXApp中添加InitInstance(),并在其中加一句
m_MyDlg.Create(IDD_DIALOG1);
5、添加一个全局的函数
int ShowDlg()
{
m_MyDlg.ShowWindow(SW_SHOW);
return 0;
}
6、在.def文件中导出ShowDlg
7、编译,连接,将生成的.dll和.lib考入我的测试程序目录中。
8、我在测试程序中添加这样的代码: #pragma comment(lib, "Dlg") int ShowDlg(); void CTestDlg::OnButton1()
{
ShowDlg();
}
----------------------------
现象:
1、点击测试程序中的Button1可以弹出对话框。
2、退出时红叉出现。定位进程序,堆栈是这样的:CMapPtrToPtr::GetValueAt(void * 0x0007085e) line 179 + 3 bytes
CHandleMap::LookupPermanent(void * 0x0007085e) line 90 + 22 bytes
CWnd::DestroyWindow() line 959 + 15 bytes
CDialog::~CDialog() line 159
CMyDlg::~CMyDlg() + 37 bytes
$E276() + 34 bytes
doexit(int 0x00000000, int 0x00000000, int 0x00000001) line 353
_cexit() line 294 + 11 bytes
_CRT_INIT(void * 0x10000000, unsigned long 0x00000000, void * 0x00000001) line 157
_DllMainCRTStartup(void * 0x10000000, unsigned long 0x00000000, void * 0x00000001) line 252 + 17 bytes
NTDLL! 77f83c48()
NTDLL! 77f8c4d4()
KERNEL32! 77e7b110()
doexit(int 0x00000002, int 0x00000000, int 0x00000000) line 392
exit(int 0x00000002) line 279 + 13 bytes
WinMainCRTStartup() line 212
KERNEL32! 77e67903()---------------------------------
按照我所说的步骤,改过程可以重现,前提是 Use MFC in a Static Library 。谁知道个中理由,分不够可以再加。
3、给对话框对应一个类m_MyDlg。
应该是:
3、给对话框对应一个类CMyDlg。m_MyDlg 被我设成了全局的,我名字起得不好,属笔误。
Regular DLL中的哪种?
是不是动态链接到MFC的规则DLL?
还是Extension DLL~
不是Extension DLL
Regular DLL using Shared MFC DLL
我刚试过,用Regular DLL with MFC staticlly linked也不行
试过了,不行呀!
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CCMyDlg m_MyDlg;
m_MyDlg.DoModal();
return 0;
}去掉m_MyDlg这个全局变量,或者你用指针
解决了没有呀?
我也遇到相同的问题了
We've been looking at Win32 DLLs that have a DllMain function and some exported functions. Now we'll move into the world of the MFC application framework, which adds its own support layer on top of the Win32 basics. AppWizard lets you build two kinds of DLLs with MFC library support: extension DLLs and regular DLLs. You must understand the differences between these two types before you decide which one is best for your needs.
Of course, Visual C++ lets you build a pure Win32 DLL without the MFC library, just as it lets you build a Windows program without the MFC library. This is an MFC-oriented book, however, so we'll ignore the Win32 option here.An extension DLL supports a C++ interface. In other words, the DLL can export whole classes and the client can construct objects of those classes or derive classes from them. An extension DLL dynamically links to the code in the DLL version of the MFC library. Therefore, an extension DLL requires that your client program be dynamically linked to the MFC library (the AppWizard default) and that both the client program and the extension DLL be synchronized to the same version of the MFC DLLs (mfc42.dll, mfc42d.dll, and so on). Extension DLLs are quite small; you can build a simple extension DLL with a size of 10 KB, which loads quickly. If you need a DLL that can be loaded by any Win32 programming environment (including Visual Basic version 6.0), you should use a regular DLL. A big restriction here is that the regular DLL can export only C-style functions. It can't export C++ classes, member functions, or overloaded functions because every C++ compiler has its own method of decorating names. You can, however, use C++ classes (and MFC library classes, in particular) inside your regular DLL. When you build an MFC regular DLL, you can choose to statically link or dynamically link to the MFC library. If you choose static linking, your DLL will include a copy of all the MFC library code it needs and will thus be self-contained. A typical Release-build statically linked regular DLL is about 144 KB in size. If you choose dynamic linking, the size drops to about 17 KB but you'll have to ensure that the proper MFC DLLs are present on the target machine. That's no problem if the client program is already dynamically linked to the same version of the MFC library. When you tell AppWizard what kind of DLL or EXE you want, compiler #define constants are set as shown in the following table. Dynamically Linked to Shared MFC Library Statically Linked* to MFC Library
Regular DLL _AFXDLL, _USRDLL _USRDLL
Extension DLL
_AFXEXT, _AFXDLL unsupported option
Client EXE _AFXDLL no constants defined
* Visual C++ Learning Edition does not support the static linking option. If you look inside the MFC source code and header files, you'll see a ton of #ifdef statements for these constants. This means that the library code is compiled quite differently depending on the kind of project you're producing. The Shared MFC DLLs and the Windows DLLs
If you build a Windows Debug target with the shared MFC DLL option, your program is dynamically linked to one or more of these (ANSI) MFC DLLs: mfc42d.dll Core MFC classes
mfco42d.dll ActiveX (OLE) classes
mfcd42d.dll Database classes (ODBC and DAO)
mfcn42d.dll Winsock, WinInet classes
When you build a Release target, your program is dynamically linked to mfc42.dll only. Linkage to these MFC DLLs is implicit via import libraries. You might assume implicit linkage to the ActiveX and ODBC DLLs in Windows, in which case you would expect all these DLLs to be linked to your Release-build client when it loads, regardless of whether it uses ActiveX or ODBC features. However, this is not what happens. Through some creative thunking, MFC loads the ActiveX and ODBC DLLs explicitly (by calling LoadLibrary) when one of their functions is first called. Your client application thus loads only the DLLs it needs. MFC Extension DLLs—Exporting Classes
If your extension DLL contains only exported C++ classes, you'll have an easy time building and using it. The steps for building the EX22A example show you how to tell AppWizard that you're building an extension DLL skeleton. That skeleton has only the DllMain function. You simply add your own C++ classes to the project. There's only one special thing you must do. You must add the macro AFX_EXT_CLASS to the class declaration, as shown here:
class AFX_EXT_CLASS CStudent : public CObject
This modification goes into the H file that's part of the DLL project, and it also goes into the H file that client programs use. In other words, the H files are exactly the same for both client and DLL. The macro generates different code depending on the situation—it exports the class in the DLL and imports the class in the client. The MFC Extension DLL Resource Search Sequence
If you build a dynamically linked MFC client application, many of the MFC library's standard resources (error message strings, print preview dialog templates, and so on) are stored in the MFC DLLs (mfc42.dll, mfco42.dll, and so on), but your application has its own resources too. When you call an MFC function such as CString::LoadString or CBitmap::LoadBitmap, the framework steps in and searches first the EXE file's resources and then the MFC DLL's resources. If your program includes an extension DLL and your EXE needs a resource, the search sequence is first the EXE file, then the extension DLL, and then the MFC DLLs. If you have a string resource ID, for example, that is unique among all resources, the MFC library will find it. If you have duplicate string IDs in your EXE file and your extension DLL file, the MFC library loads the string in the EXE file. If the extension DLL loads a resource, the sequence is first the extension DLL, then the MFC DLLs, and then the EXE. You can change the search sequence if you need to. Suppose you want your EXE code to search the extension DLL's resources first. Use code such as this:
HINSTANCE hInstResourceClient = AfxGetResourceHandle();
// Use DLL's instance handle
AfxSetResourceHandle(::GetModuleHandle("mydllname.dll"));
CString strRes;
strRes.LoadString(IDS_MYSTRING);
// Restore client's instance handle
AfxSetResourceHandle(hInstResourceClient);You can't use AfxGetInstanceHandle instead of ::GetModuleHandle. In an extension DLL, AfxGetInstanceHandle returns the EXE's instance handle, not the DLL's handle.