VC + + dynamic link library (DLL) programming in Layman's (c)

Source: Internet
Author: User

Before we introduce the non-MFC DLLs, this section will describe in detail the creation and use of MFC rules DLLs.

In addition, since the beginning of this article, I have received some e-mails from readers. Some readers put forward some questions, the author will be in the last series of this article to select the typical problems to answer. Because of the relationship of time, for the reader friend's letter, I can not reply to each, but also look Haihan! Due to the author's limited level, the text inevitably have errors and flaws, but also sincerely welcome readers friends to correct me!

5. MFC rules DLLs

5.1 Overview

The concept of the MFC rules DLL is embodied in two ways:

(1) It is MFC's

"is MFC" means that MFC can be used inside this DLL;

(2) It's a rule.

"is regular" means that it differs from the MFC extension DLL, although MFC can be used inside the MFC rule DLL, but its interface with the application cannot be MFC. The MFC extension DLL and the application interface can be MFC, and you can export a derived class of an MFC class from an MFC extension DLL.

Regular DLLs can be called by applications written by all languages that support DLL technology, including applications that use MFC, of course. In this dynamic connection library, a class that inherits from CWinApp is included, and the DllMain function is automatically provided by MFC.

The Regular DLLs are divided into two categories:

(1) A regular DLL that is statically linked to MFC

Static links to MFC's regular DLLs and MFC libraries (including MFC extension DLLs) are statically linked, and the code for the MFC library is generated directly in the. dll file. When calling this DLL's interface, MFC uses the DLL's resources. Therefore, there is no need to switch the module state in a regular DLL that is statically linked to MFC.

A rule DLL generated using this method has a large program, and may contain duplicate code.

(2) Dynamically linked to MFC's regular DLLs

A regular DLL that is dynamically linked to MFC can dynamically link to an MFC DLL and any MFC extension DLLs at the same time as the executable file that uses it. When using the MFC shared library, by default, MFC uses the resource handle of the main application to load the resource template. This way, the system may not be able to obtain the correct resources when a resource with the same ID exists in the DLL and the application (that is, the so-called resource duplication problem). Therefore, for a regular DLL that shares an MFC DLL, we must switch the module so that MFC can find the correct resource template.

We can set the MFC rules in Visual C + + DLLs to be statically linked to an MFC DLL or dynamically linked to an MFC DLL. 8, select the General menu or options for Visual C + + project-Settings, and then set it up in Microsoft Foundation classes.

Figure 8 Setting up a dynamic/static link to an MFC DLL

5.2 Creating an MFC Rule DLL

Let's step through the process of creating an MFC regular DLL using the MFC Wizard, first create a new project,9, and choose the type of Project as MFC AppWizard (DLL). Click OK to enter the dialog box shown in 10.

Figure 9 Creation of an MFC DLL project

Figure 10 shows the category of the MFC DLL in the 1 area of the dialog box.

Zone 2 Select whether to support Automation (automation) technology, Automation allows users to manipulate another application or component in one application. For example, we can take advantage of Microsoft Word or Microsoft Excel tools in the application, which is transparent to the user. Automation technology can greatly simplify and accelerate the development of applications.

Zone 3 Select whether Windows Sockets is supported, and when this item is selected, the application can communicate on the TCP/IP network. The InitInstance member function of the CWinApp derived class initializes support for the communication side, and the StdAfx.h file in the project automatically include the <AfxSock.h> header file.

The InitInstance member function after adding socket communication support is as follows:

BOOL cregulardllsocketapp::initinstance () {if (!  AfxSocketInit ()) {AfxMessageBox (idp_sockets_init_failed); return FALSE;} return TRUE;}

Figure ten MFC DLL creation options

5.3 A simple MFC rule DLL

An example of this DLL (which belongs to a regular DLL statically linked to MFC) provides a dialog box shown in 11.

Figure one MFC Rule DLL example

The dialog box is added in the DLL in the same way as in an MFC application.

When you click on the Hello button of the dialog box in the DLL shown in Figure 11, a "Hello,pconline User" dialog box is clicked, and the following is the relevant file and source code, which removes most of the comments automatically generated by the MFC Wizard (download the project attachment):

First set of files: Declaration and implementation of CWinApp inheriting classes

//Regulardll.h:main header file for the Regulardll DLL#if!defined (Afx_regulardll_h__3e9cb22b_588b_4388_b778_b3416adb79b3__included_)#defineAfx_regulardll_h__3e9cb22b_588b_4388_b778_b3416adb79b3__included_#if_msc_ver > 1000#pragmaOnce#endif //_msc_ver >#ifndef __afxwin_h__#errorInclude ' stdafx.h ' before including this file for PCH#endif#include"resource.h" //Main symbolsclassCregulardllapp: Publiccwinapp{ Public: Cregulardllapp ();D eclare_message_map ()};#endif//RegularDll.cpp:Defines The initialization routines for the DLL.#include"stdafx.h"#include"RegularDll.h"#ifdef _DEBUG#defineNew Debug_new#undefThis_fileStatic CharThis_file[] =__file__;#endifBegin_message_map (Cregulardllapp, CWinApp) end_message_map ()///////////////////////////////////////////////////////////////////////////////Cregulardllapp ConstructionCregulardllapp::cregulardllapp () {}///////////////////////////////////////////////////////////////////////////////The one and only Cregulardllapp objectCregulardllapp Theapp;

A class Cregulardllapp that inherits from CWinApp is defined in this set of files, and an instance of Theapp is defined at the same time. At first glance, you'll think of it as an MFC application, because the MFC application also contains a class that adds "App" to the class name after the project name (and inherits from the CWinApp Class), and also defines a global instance of this class, Theapp.

We know that in an MFC application CWinApp supersedes the WinMain in the SDK program, and the work done by the SDK WinMain is done by the three functions of CWinApp:

Virtual BOOL initapplication ();
Virtual BOOL InitInstance ();
Virtual BOOL Run (); The "source of living Water" in the legendary MFC program

However, the MFC rule DLL is not an MFC application, and the class that inherits from CWinApp does not contain a message loop. This is because the MFC rule DLL does not contain the CWinApp::Run mechanism, and the main message pump is still owned by the application. If the DLL generates a modeless dialog box or has its own main frame window, the application's main message pump must call the function exported from the DLL to call the PreTranslateMessage member function.

In addition, the MFC rule DLL, like in an MFC application, requires that the initialization of elements in all DLLs be put into the InitInstance member function.

Second set of File custom dialog box class declaration and implementation (click to view Attachment)

Analysis:

This part of the programming is no different from the general application at all, so we can still use the MFC Class Wizard to automatically add events to the controls on the dialog box. The MFC Class wizard will still generate a message-map macro similar to on_bn_clicked (Idc_hello_button, Onhellobutton).

Resource files in the third set of file DLLs

// {{no_dependencies}} // Microsoft Developer Studio generated include file. // used by Regulardll.rc // #define Idd_dll_dialog#define Idc_hello_button 1000

Analysis:

The use of resources in MFC regular DLLs is no different from using resources in MFC applications, so we can use Visual C + + resource editing tools to make resource additions, deletions, and property changes.

Fourth set of files MFC rules DLL interface functions

" StdAfx.h "  "DllDialog.h"extern"C"void Showdlg (void) {cdlldialog dlldialog;dlldialog.domodal ();}

Analysis:

This interface does not use MFC, but it can call the MFC extension class Cdlldialog function, which embodies the "rules" of the class.

As with non-MFC DLLs, we can export the interfaces in the MFC rules DLL using the __declspec (dllexport) declaration or the way that is derived in. def.

5.4 Calls to MFC rule DLLs

The author wrote 12 of the dialog MFC program (download the project attachment) to invoke the 5.3 section of the MFC Rule DLL, the dialog box on this program click on the "Call DLL" button when the 5.3 section of the MFC Rule DLL dialog box.

Diagram of the MFC rule DLL invocation example

The following is the message handler function for the call DLL button click event:

voidCregulardllcalldlg::oncalldllbutton () {typedefvoid(*lpfun) (void); HINSTANCE hDLL; //DLL HandlehDLL = LoadLibrary ("RegularDll.dll");if(null==hDLL) {MessageBox ("DLL failed to load");} Lpfun Addfun; //function PointersLpfun Pshowdlg = (lpfun) GetProcAddress (hDLL,"Showdlg");if(null==Pshowdlg) {MessageBox ("function search failure in DLL");} Pshowdlg ();}

We can still implicitly invoke the MFC rule DLL in the EXE program, simply copy the. lib file and the. dll file generated by the DLL project into the same directory as the current project and add it at the top of the RegularDllCallDlg.cpp file (the implementation file for the dialog class shown in Figure 12):

#pragma comment (lib, "RegularDll.lib")void Showdlg (void);

and replace void Cregulardllcalldlg::oncalldllbutton () with the following:

void Cregulardllcalldlg::oncalldllbutton () {Showdlg ();}

5.5 Module switching for a regular DLL that shares an MFC DLL

The application process itself and each DLL module it invokes have a globally unique hinstance handle that represents the starting address of a DLL or EXE module in the process virtual space. The module handle for the process itself is generally 0x400000, and the default handle for the DLL module is 0x10000000. If the program loads multiple DLLs at the same time, each DLL module will have a different hinstance. The application relocated the DLL when it was loaded.

The rules DLLs that share MFC DLLs (or MFC extension DLLs) involve hinstance handle problems, and hinstance handles are particularly important for loading resources. EXE and DLLs have their own resources, and the IDs of those resources can be duplicated, and the application needs to switch from the resource module to find the right resources. If the application requires resources from a DLL, the resource module handle should be specified as the module handle of the DLL, and if the resource contained in the EXE file is required, the resource module handle should be specified as the module handle of the EXE.

This time we create a regular DLL that is dynamically linked to the MFC DLL (download this project attachment), which contains 13 of the dialog box.

dialog box in the diagram in the DLL

dialog box in the figure in EXE

The dialogs in Figure 13 and figure 14 are the same except for caption (to differentiate).

In particular, in the DLL and EXE we use the same resource id=2000 in the dialog boxes of Figure 13 and figure 14, which have the following macros in the DLL and EXE project resource.h:

// the ID of the dialog box in the DLL #define Idd_dll_dialog//EXE in the ID of the dialog box#define Idd_exe_dialog 2000

As with the 5.3 section of the regular DLL that statically links the MFC DLL, we also define the interface function Showdlg in the regular DLL, with the following prototype:

" StdAfx.h "  "SharedDll.h"void showdlg (void//  Open the dialog box with ID 2000 dlg. DoModal ();}

Instead, add the following message handler for the Click event for the invoke DLL in the Application Engineering main dialog box:

void Cshareddllcalldlg::oncalldllbutton () {Showdlg ();}

We thought that clicking "Call dll" would pop up the dialog box in the DLL shown in 13, but the scary thing happened and we saw the dialog box in the exe shown in Figure 14!

Surprised?

The root cause of this problem is that applications that share MFC DLL (or MFC extension DLLs) with the MFC rule DLLs always use EXE resources by default, and we have to switch the handle of the resource module, which is implemented in three ways:

Method one is used in DLL interface functions:

Afx_manage_state (AfxGetStaticModuleState ());

Let's change the interface function Showdlg in the DLL to:

void Showdlg (void) {// Method 1: Change at start of function, restore at end of function // afx_manage_state ( AfxGetStaticModuleState ()); module state switching as the first // clause of an interface function afx_manage_state ( AfxGetStaticModuleState ()); CDialog dlg (idd_dll_dialog); // Open the dialog box with ID 2000 dlg. DoModal ();}

This time we click on the "Call DLL" button in the EXE program, which pops up a 13 dialog box in the DLL! Hey, pop up the right dialog resource.

AfxGetStaticModuleState is a function whose prototype is:

afx_module_state* AFXAPI afxgetstaticmodulestate ();

The function's function is to create an instance of the Afx_module_state class (module global data, which is the module state) on the stack (which means its scope is local), set it, and return its pointer pmodulestate.

The prototype of the Afx_module_state class is as follows:

 //  Afx_module_state (global data for a module)  class  afx_module_state: public   cnotrackobject{ public  : #ifdef _afxdllafx_module_state (BOOL bdll, WNDPROC pfnafxwndproc, DWORD dwversion); Afx_module_state (BOOL bdll, WNDPROC pfnafxwndproc, DWORD dwversion,bool bsystem);   #else  afx_module_state (BOOL bdll);   #endif  ~afx_module_state (); CWINAPP  * M_pcurrentwinapp; HINSTANCE M_hcurrentinstancehandle; HINSTANCE M_hcurrentresourcehandle; LPCTSTR m_lpszcurrentappname, .....  //  Omit the later part of } 

The Afx_module_state class uses its constructors and destructors for the storage module state scene and the recovery site, similar to the call instruction in the assembly to save and restore the PC pointer and SP Register, Interrupt Service program interrupts the field stack and restore as well as the operating system thread scheduling task control block save and restore.

Many seemingly irrelevant points of knowledge are incredibly similar!

Afx_manage_state is a macro whose prototype is:

Afx_manage_state (afx_module_state* pModuleState)

This macro is used to set the pmodulestate to the current active module state. When you leave the scope of the macro (and leave the scope of the object that Pmodulestate points to on the stack), the previous module state will be restored by the Afx_module_state's destructor.

Method Two is used in DLL interface functions:

AfxGetResourceHandle();
AfxSetResourceHandle(HINSTANCE xxx);

AfxGetResourceHandle is used to get the current resource module handle, while AfxSetResourceHandle is used to set the resource module handle that the program is currently using.

Let's change the interface function Showdlg in the DLL to:

void Showdlg (void) {// state Change of Method 2 hinstance save_hinstance = AfxGetResourceHandle () ; AfxSetResourceHandle (theapp.m_hinstance); CDialog dlg (idd_dll_dialog); // Open the dialog box with ID 2000 dlg. DoModal (); // state Restore of Method 2 AfxSetResourceHandle (save_hinstance);}

With the reasonable change of AfxGetResourceHandle and AfxSetResourceHandle, we have the flexibility to set the resource module handle of the program, and a method can only recover the module handle when the DLL interface function exits. Method Two is different, if SHOWDLG is changed to:

externCshareddllapp Theapp;//need to declare theapp external global variablesvoidShowdlg (void){//state Change of Method 2HINSTANCE Save_hinstance =AfxGetResourceHandle (); AfxSetResourceHandle (theapp.m_hinstance); CDialog dlg (idd_dll_dialog);//Open the dialog box with ID 2000dlg. DoModal ();//state Restore of Method 2AfxSetResourceHandle (save_hinstance);//After you use Method 2, the following action will be made for the application's resourcesCDialog Dlg1 (Idd_dll_dialog);//Open the dialog box with ID 2000Dlg1. DoModal ();}

Method Three is switched by the application itself

The switch of the resource module can be done by the application itself (download the project attachment) in addition to the DLL interface function.

Now let's change the interface function in the DLL to the simplest:

void Showdlg (void// opens a dialog box with ID 2000 dlg.) DoModal ();}

Instead, change the Oncalldllbutton function of the application to:

voidCshareddllcalldlg::oncalldllbutton () {//Method 3: State switching by the application itself//get EXE module handleHINSTANCE Exe_hinstance =GetModuleHandle (NULL);//or hinstance exe_hinstance = AfxGetResourceHandle ();//Get DLL Module handleHInstance dll_hinstance = GetModuleHandle ("SharedDll.dll"); AfxSetResourceHandle (dll_hinstance); //Toggle StatusShowdlg ();//A dialog box for the DLL appearsAfxSetResourceHandle (exe_hinstance);//Recovery Status//Resource module is restored before calling ShowdlgShowdlg ();//The exe's dialog box is now displayed}

The Win32 function in method three GetModuleHandle can get the module handle of a DLL based on the file name of the DLL. If you need to get a handle to the EXE module, you should call GetModuleHandle with a null parameter.

The difference between method three and method two lies in the method of using AfxGetResourceHandle and afxsetresourcehandle to switch the handle of the resource module in the application. Similarly, clicking on the Call DLL button in the main Application dialog box will also see two dialogs, one after the other, in the dialog box in the DLL (Figure 13) and in the EXE (Figure 14).

In the next section we will analyze and illustrate the MFC extension DLLs in detail, and you are welcome to continue to follow this series.

VC + + dynamic link library (DLL) programming in Layman's (c)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.