VC ++ notes-create a dynamic Connection Library

Source: Internet
Author: User
Tags case statement comparison table import database

In some cases, you must use the dynamic Connection Library:

1. Multiple applications share code and data. For example, the components of the Office software have similar appearances and functions, which are achieved by sharing dynamic connection libraries.

2. When the hook program filters system messages, it must use a dynamic Connection Library.

3. the device driver must be a dynamic Connection Library.

4. If you want to use your own control in the dialog box editor, you must also use the dynamic Connection Library.

5. The dynamic Connection Library divides a large application into several small modules in a natural way, which facilitates the division of labor and cooperation among the members of the group. In addition, each module can be upgraded independently. If a member in the group develops a set of Utility Routines, he can place these routines in a dynamic connection library for other members of the group to use.

6. Dynamic connection libraries are often used to internationalize applications. You can use the dynamic connection library to store information about a country or language. For different versions, use different dynamic connection libraries. When using Appwizard to generate an application, we can specify the language used by the resource file, which is achieved by providing different dynamic connection libraries.

MFC supports the creation of two types of dynamic connection libraries:

User dynamic Connection Library

MFC extension class library.

9.3.1 user dynamic Connection Library (_ usrdll)

 

The user's dynamic Connection Library generally uses the C language interface. To create a dynamic Connection Library, select File> New to bring up the new dialog box. On the projects tab, select "Win32 dynamic-Link Library ". Visual c ++ creates the project files and Mak files required for the dynamic Connection Library.

Add the following two files to the Project (Project-add to project-files menu ).

File 1: mymaths. cpp

////////////////////////////

// Mymaths. cpp

//

// A maths api dll.

//

///////////////////////////

# Include <windows. h>

// Declare the DLL Functions prototypes

Int Summary (INT );

Int factorial (INT );

//////////////////////////

// Dllentrypoint (): the entry point of the DLL

//

/////////////////////////

Bool winapi dllentrypoint (hinstance hdll, DWORD dwreason,

Lpvoid reserved)

{

Switch (dwreason)

{

Case dll_process_attach:

{

// Some initialization code

Break;

}

Case dll_process_detach:

{

// Some code for cleanup

Break;

}

}

Return true;

}

Int Summary (int n)

{

Int sum = 0;

Int I;

For (I = 1; I <= N; I ++)

{

Sum + = I;

}

Return sum;

}

Int factorial (int n)

{

Int fact = 1;

Int I;

For (I = 1; I <= N; I ++)

{

Fact = fact * I;

}

Return fact;

}

File 2: mymaths. Def

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Mymaths. Def

;

; The def file for the mymaths. dll.

;

Library mymaths

Code preload moveable discardable

Data preload single

Exports

; The names of the DLL Functions

Summary

Factorial

At the beginning of mymaths. CPP, the two functions of the dynamic Connection Library are declared: Summary and factorial. The following is the definition of the dllentrypoint () function. As the name suggests, dllentrypoint () is the portal for dynamic database connection. Applications can use this portal to access the services provided by the dynamic database connection. The dllentrypoint () subject is a switch/case statement:

Switch (dwreason)

{

Case dll_process_attach:

{

// Some initialization code

Break;

}

Case dll_process_detach:

{

// Some code for cleanup

Break;

}

}

Some initialization code when the case dll_process_attach branch can be added to the dynamic connection library for execution. Some cleanup code when case dll_process_detach is added to the dynamic connection library when it is detached, such as releasing the memory applied for during the dynamic Connection Library running.

The dllentrypoint () function defines the summary and factorial functions. Their definitions are exactly the same as those of the previous static library. You can put any function here.

In addition, we need a mymaths. Def file. This file records the name of The dll library function that can be used by external applications. These name information and the corresponding function location information will be compiled into the dynamic connection library file, and then the application finds the corresponding function based on the function name and Function Location comparison table.

Press F7 to compile the project. Visual C ++ generates a mymaths. dll dynamic connection library file under the mymaths \ DEBUG directory.

Now, let's use the dynamic connection library that we just generated. Instead of generating a new program, we modify the test program when testing the static library. First, copy mymaths. dll under the mymaths \ DEBUG directory to the test \ DEBUG directory. When the test program runs, it searches for dynamic connection library files in this directory. Modify testdlg. h and add the loaddll () function declaration to it. For details, see listing 9.4. Loaddll is used to load the dynamic Connection Library.

Configuration 9.4: Modified dialog box header file

Class ctestdlg: Public cdialog

{

// Construction

Public:

Ctestdlg (cwnd * pparent = NULL); // standard Constructor

Protected:

Void loaddll ();

//......

}

Modify testdlg. cpp, as shown in listing 9.5.

Listing 95. testdlg. cpp File

// Testdlg. cpp: implementation file

//

# Include "stdafx. H"

# Include "test. H"

# Include "testdlg. H"

// # Include "mymath. H" // comment out the mymath. h header file

# Ifdef _ debug

# Define new debug_new

# UNDEF this_file

Static char this_file [] = _ file __;

# Endif

// The instance of the mymaths. dll library

Hinstance ghmathsdll = NULL;

// Declare the summary () function from the mymaths. dll libray.

Typedef int (* Summary) (INT );

Summary;

// Declare the factorial () function from

// The mymaths. dll library.

Typedef int (* factorial) (INT );

Factorial factorial;

//////////////////////////////////////// /////////////////////////////////////

// Caboutdlg Dialog used for app about

Class caboutdlg: Public cdialog

{

//...

};

// Some member function definitions of caboutdlg

// Some member function definitions of ctestdlg

Void ctestdlg: onsum ()

{

// Todo: add your control notification handler code here

Loaddll ();

Int nsum = Summary (10 );

Cstring sresult;

Sresult. Format ("sum (10) = % d", nsum );

Afxmessagebox (sresult );

}

Void ctestdlg: onfactorial ()

{

// Todo: add your control notification handler code here

Loaddll ();

Int nfact = factorial (10 );

Cstring sresult;

Sresult. Format ("10! = % D ", nfact );

Afxmessagebox (sresult );

}

Void ctestdlg: loaddll ()

{

// If the DLL has been loaded, return

If (ghmathsdll! = NULL)

{

Return;

}

// Load the mymaths. dll file.

Ghmathsdll = loadlibrary ("mymaths. dll ");

// If the DLL fails to be loaded, prompt the user

If (ghmathsdll = NULL)

{

Afxmessagebox ("cannot load DLL file! ");

}

// Obtain the address of the summary function in the DLL

Summary = (Summary) getprocaddress (ghmathsdll, "summary ");

// Obtain the address of the factorial function in the DLL.

Factorial = (factorial) getprocaddress (ghmathsdll, "factorial ");

}

 

At the beginning of the testdlg. cpp file, add:

// The instance of the mymaths. dll library

Hinstance ghmathsdll = NULL;

// Declare the summary () function from the mymaths. dll libray.

Typedef int (* Summary) (INT );

Summary;

// Declare the factorial () function from

// The mymaths. dll library.

Typedef int (* factorial) (INT );

Factorial factorial;

First, add a global variable of ghmathsdll, which is the handle loaded by the dynamic Connection Library (like the application, each dynamic Connection Library will have a handle corresponding to it ). The application uses a handle to access functions in the database. Then add the Type Definitions of the summary and factorial function pointers.

In the loaddll () function definition, check whether the handle of the dynamic Connection Library is empty. If it is empty, use loadlibrary to load the dynamic Connection Library. Then, use getprocaddress to get the addresses of the summary and factorial functions.

At the beginning of the onfactorial and onsummary functions, call loaddll () to load the dynamic Connection Library. Compile and run the program. Press the factorial button to test the program.

How does an application find DLL files?

The application test searches for dynamic connection library files in the following order:

  • Current Directory (So copy the dynamic Connection Library to the DEBUG directory because the executable file is in this directory)
  • Windows Directory
  • Windows System directory
  • Directory set in Path Environment Variable
  • Directory included in the directory table of the ing Network

 

How to call functions in a dynamic Connection Library

There are two ways to call functions in the dynamic Connection Library:

1. import data to the database through import:

Use the implib tool provided by Visual C ++ to generate an import database for the dynamic connection database, and design a header file for import database:

# Ifndef _ mymath_h

# DEFINE _ mymath_h

Extern "C"

{

Int Summary (int n );

Int factorial (int n );

}

# Endif

Include this header file in the source file that uses the dynamic connection library. When you connect to an application, this header file will be connected to the database. In this way, the application can use functions in the dynamic Connection Library as freely as the static Connection Library. Copy the dynamic Connection Library to the directory where the executable files of the application are located (\ test \ Debug.

This is a common method. In fact, applications access Windows API functions in this way. Windows generates the import library for its kernel dynamic Connection Library and provides the header file. During compilation, the application adds the imported information to the executable file, and accesses the API function through the imported information at runtime.

2. Specify the library and function address directly.

This method is suitable for dynamic connection libraries that provide services such as file format conversion. For example, a program has multiple dynamic connection libraries used to access JPG, BMP, GIF, and other image file formats. These dynamic connection libraries provide the same library function interfaces. In this case, the database function cannot be specified using the import/export method. You can use the following method to solve this problem.

Handle hlibrary;

Farproc lpfunc;

Int nformat;

If (nformat = JPEG) // if the format is JPEG, load the JPEG dynamic Connection Library.

{

Hlibrary = loadlibrary ("Jpeg. dll ");

}

Else // GIF format

Hlibrary = loadlibrary ("GIF. dll ");

If (hlibrary> = 32)

{

Lpfunc = getprocaddress (hlibrary, "ReadImage ");

If (lpfunc! = (Farproc) null)

(* Lpfunc) (lpctstr) strfilename );

Freelibrary (hlibrary );

}

Load the loadlibrary function into the required dynamic Connection Library and return the handle of the library. If the handle is less than 32, the loading fails. For error meanings, see the relevant manual. The getprocaddress function uses the function name to obtain the function address. With this function address, you can access functions that dynamically connect to the database.

Freelibrary checks the reference counter of the dynamic connection library to determine whether other programs are using this dynamic Connection Library. If no, the dynamic Connection Library is removed from the memory. If yes, the counter of the dynamic Connection Library is reduced by 1. Loadlibrary adds the reference count to 1.

You can also use the MFC class in the user's dynamic Connection Library. In this case, you can choose static connection or dynamic connection to use the MFC library.

9.3.2 MFC extension class library (_ afxdll)

 

In addition to creating a user dynamic connection library with a C language interface, MFC also allows users to create a derived class of the MFC class in the dynamic connection library. These classes appear as a natural extension of the MFC class, it can be used by other MFC applications, just like using a common MFC class.

Create extension class library

To create an extension class library, select File> new, and select MFC Appwizard (DLL) in projects ). The MFC Appwizard 1of 1 dialog box is displayed. Select MFC extension DLL (using shared mfc dll ). Appwizard generates the framework required by the extension DLL.

Instead of creating a dynamic connection library, we will use the dllhusk program in the Visual C ++ example (under the samples \ MFC \ Advanced \ dllhusk directory) to describe how to create and use the extension class library.

The dllhusk project workspace contains three projects: dllhusk, testdll1, and testdll2.

Testdll1 and testdll2 define several extension classes: ctextdoc, chelloview, and clistoutputframe. dllhusk is a sample program that uses these classes.

In the clistoutputframe declaration, add afx_ext_class to indicate that it is an MFC extension class.

Class afx_ext_class clistoutputframe: Public extends ichildwnd

{

...

}

The function definition also contains the afxdllx. h header file.

// Initialization of MFC extension DLL

# Include "afxdllx. H" // Standard MFC extension DLL routines

The usage of member functions of the class is roughly the same as that of the class in the application.

In the clistoutputframe class definition file, a C function is also provided. Its function declaration is in the Class header file testdll2.h:

// Initialize the DLL, register the classes etc

Extern "C" afx_ext_api void winapi inittestdll2 ();

This function is used to initialize the dynamic Connection Library and registration class:

// Exported DLL Initialization is run in context of running application

Extern "C" Void winapi inittestdll2 ()

{

// Create a new cdynlinklibrary for this app

New cdynlinklibrary (extensiondll );

// Nothing more to do

}

In addition, a dllmain function must be provided in the source file:

Dllmain (hinstance, DWORD dwreason, lpvoid lpreserved)

This function is similar to the preceding dllentrypoint.

The extension class library also requires a Def file that contains information about available functions in the dynamic Connection Library. Currently, the dynamic Connection Library contains classes, so the function name is different from the user's dynamic Connection Library.

Exports

? Addstring @ clistoutputframe qaaxpbd @ Z

?? _ 7clistoutputframe @ 6B @

?? _ Gclistoutputframe @ uaapaxi @ Z

? Oneditcut @ clistoutputframe @ iaaxxz

? _ Messageentries @ clistoutputframe @ 0qbuafx_msgmap_entry @ B

?? 0clistoutputframe @ Qaa @ xz

?? 1clistoutputframe @ uaa @ xz

? Clear @ clistoutputframe qaaxxz

? Oneditclear @ clistoutputframe @ iaaxxz

? Oneditcopy @ clistoutputframe @ iaaxxz

Inittestdll2

......

For more information about function name extension, see the Visual C ++ help documentation.

Use extended dynamic Connection Library

To use the extended class library, you must include the header file of the class library in the project. Then initialize the class library in the appropriate location. dllhusk completes this work in initinstance.

Bool chuskapp: initinstance ()

{

//...

Inittestdll1 ();

Inittestdll2 ();

//...

}

Then you can use the classes defined in the extension class library just like using the common MFC class.

M_plistout = new clistoutputframe;

Access resources in DLL

When an application uses resources, it searches for resources in the following order: first, it looks for the application itself to see if there are corresponding resources; if not, it looks for mfc400.dll (or mfc400d. DLL, which contains debugging information ). Find the resources in the dynamic Connection Library of the application. If you want to directly use resources in the DLL without going through the above search order, you can use the afxgetresoucehandle () and afxsetresourcehandle () functions.

The afxgetresourcehandle () and afxsetresoucehandle () functions are used to save the old resource handle and set the new resource handle respectively. For example, to directly load a bitmap resource from a DLL, you can call the following method:

Cbitmap mybitmap;

Hinstance hinstold = afxgetresourcehandle ()

Afxsetresoucehandler (extensiondll. hmodule );

If (! Mybitmap. loadbitmap (idr_bitmap ));

{

// Restore the old resouce chain and Return Error

Afxsetresoucehandle (hinstold );

Return false;

}

Afxsetresoucehandle (hinstold );

// Use this bitmap...

Return true;

You can also use findresource () to search for the resource table and find the given resource.

Hrsrc findresource (

Hmodule Hmodule,

 

Lpctstr Lpname,

 

Lpctstr Lptype

 

);

FindresourceThere are three parameters. The first parameter is the module handle, and the second parameter is the name of the resource to be searched, for example, "mydialog". The third parameter is the resource type. For more information, see the Visual C ++ documentation. If the search is successful, the resource handle is returned. You can use loadresouce to load resources with this handle as a parameter.

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.