VC ++ in-depth explanation (17): Dynamic Link Library

Source: Internet
Author: User

Static Library
Functions and data are compiled into a binary file (. Lib ). When a static library is used to compile and connect executable files, the linker copies these functions and data from the library, and combine them with other modules of the application to create the final executable file (. EXE ). When a product is released, you only need to publish executable files, and do not need to publish static libraries.
It has the following features:
1. The compiled executable file contains the required function code, occupying a large disk space. (But it can avoid the embarrassing situation that the user's computer does not have the library you used for development .)
2. If multiple processes that call the same database run simultaneously in the memory, the memory will store multiple identical codes.
Dynamic library
When using a dynamic library, we often provide two files: the import library (. Lib) file and the DLL (. dll) file. The introduced file contains the DLL exported functions and variable symbol names, while. dll contains the actual functions and data of the DLL. When a dynamic library is used, you only need to connect the DLL import file to the database when compiling and connecting the executable file, the function code and data of the DLL are not copied to the executable file. When the executable program runs, the required DLL is loaded and mapped to the address space of the process, then access the function exported in the DLL. In this case, in addition to the executable files, the dynamic link library to be called by the program is also released.
The advantage of using a dynamic library is that it can save disk space and memory. If multiple applications need to access the same function, you can provide the function in the form of DLL, so that only one copy of the DLL is required on a machine, this saves disk space. If multiple programs call the same DLL, the page of the DLL only needs to be stored in the memory once, And all applications can share its page.

First, we create an empty Win32 dynamic link library and add two functions to it:

int add(int a, int b){return a + b;}int subtract(int a, int b){return a - b;}

After the build, under the DEBUG directory of the project, there will be a DLL file corresponding to the project. This dll cannot be used at present, because neither of these functions is "exported ". We can use the command line tool dumpbin provided by Visual Studio to view:
D: \ myprograms \ MFC \ ch_19_dll1 \ debug> dumpbin-Exports ch_19_dll1.dll
Microsoft (r) COFF binary file dumper version 6.00.8168
Copyright (c) Microsoft Corp 1992-1998. All rights reserved.

Dump of file ch_19_dll1.dll

File Type: DLL

Summary

7000. Data
1000. idata
2000. RDATA
2000. reloc
2a000. Text

There is no function-related information.

To allow the DLL to export some functions, add the identifier _ declspec (dllexport) before each function to be exported ).
At this point, you can see:
Ordinal hint RVA name

1 0 limit 100a? Add @ yahhh @ Z
2 1 00001005? Subtract @ yahhh @ Z

Where? Add @ yahhh @ Z and? Subtract @ yahhh @ Z is discussed in detail in my other blog: Fully summarized _ cdecl _ fastcall, _ stdcall ,__ thiscall, it is described as follows:
First, the compiler adds a question mark (?) before the function name ?; Second, because it is called by _ cdecl, add ya; again, h Represents the int type, 3 h Represents the return value, the first parameter, the second parameter, end with @ Z.

With the dynamic link library, we need to load them in the program. Two optional methods are available: the DLL is loaded by implicit link, and the DLL is loaded.
Let's first look at implicit loading. Create an MFC dialog box application, and then add two buttons, one for addition and the other for subtraction. The message response function is as follows:

extern int add(int a, int b);extern int subtract(int a, int b);void CCH_19_DllTestDlg::OnBtnAdd() {// TODO: Add your control notification handler code hereCString str;str.Format("5 +3 = %d",add(5,3));MessageBox(str);}void CCH_19_DllTestDlg::OnBtnSubtract() {// TODO: Add your control notification handler code hereCString str;str.Format("5 - 3 = %d",subtract(5,3));MessageBox(str);}

The add and subtract functions in the dynamic link library are called, so they are declared as external functions here.
How to load it?
Under the DEBUG directory of our dynamic link library, Set *. copy the Lib file to the folder where the MFC program is located, and add the entire lib file to the project> Settings> link. Then the program can compile the link. We can use dumpbin to view:
D: \ myprograms \ MFC \ ch_19_dlltest \ debug> dumpbin-imports ch_19_d
Microsoft (r) COFF binary file dumper version 6.00.8168
Copyright (c) Microsoft Corp 1992-1998. All rights reserved.

Dump of file ch_19_dlltest.exe

File Type: executable Image

Section contains the following imports:

Ch_19_dll1.dll
4052c0 import Address Table
40508c Import Name table
0 time date stamp
0 index of first forwarder reference

1? Subtract @ yahhh @ Z
0? Add @ yahhh @ Z
Other parts are omitted.
We can see that this executable file needs to import the subtract and add functions.
The directory where the project resides), the current directory (the directory where. cpp is located), the system directory, and the Environment Variable directory. We can copy the corresponding. dll file. The program can be successfully executed.

In addition to dumpbin, we can also use a visual tool provided by VC ++: Depends for viewing. I will not mention it here.

In addition to extern, we can also use _ declspec (dllimport) to indicate that the function is loaded from the dynamic link library. That is:

//extern int add(int a, int b);//extern int subtract(int a, int b);__declspec(dllimport) int add(int a, int b);__declspec(dllimport) int subtract(int a, int b);

This is just a descriptive example. In practice, we usually do not write programs like this. After we hand over the DLL to the user, the user does not know the functions in the DLL. it is inconvenient to guess the function prototype through the dumpbin and depends compilation tools described earlier. The correct method is to add a header file for the DLL and add the function declaration and comments in the header file. Add the following in the header file:

__declspec(dllimport) int add(int a, int b);__declspec(dllimport) int subtract(int a, int b);

Note that because the header file is used by the user, it indicates that these functions are imported from the DLL. In our Dialog Box program, add:
# Include ".. \ ch_19_dll1 \ ch_19_dll1.h"

Sometimes, we hope that the functions in the dll library can be used not only by the customer, but also by the Library itself. Then we need to use the pre-compiled command to implement it. In the header file:

#ifdef DLL1_API#else#define DLL1_API __declspec(dllimport)#endifDLL1_API int add(int a, int b);DLL1_API int subtract(int a, int b);

First, determine whether or not to define the dllw.api. If it is defined, nothing will be done. Otherwise, the dllw.api will be defined as _ declspec (dllimport), and then replace dllw.api with _ declspec (dllimport ).
In the source file:

#define DLL1_API _declspec(dllexport)#include "CH_19_Dll1.h"int add(int a, int b){return a + b;}int subtract(int a, int b){return a - b;}

At this time, these functions are the same as the functions we previously wrote and can be called to each other.
Let's take a closer look. When compiling the DLL, the source file defines the dllw.api and expands the header file. In this case, because the dll1_api has been defined, the declaration of the function is compiled directly, indicating that the function is exported from the dynamic link library.
When a user program calls this DLL, as long as the user program does not define the dll1_api, The dll1_api is defined as _ declspec (dllimport ).
Let's take a look at how to export the C ++ class from the dynamic link library:
Declare in the header file:

class DLL1_API Point{public:void output(int x, int y);};

Define in the source file:

Void point: output (int x, int y) {// obtain the handle of the current window hwnd = getforegroundwindow (); // obtain dchdc HDC = getdc (hwnd ); char Buf [20]; memset (BUF,); sprintf (BUF, "x = % d, y = % d", x, y); textout (HDC, buf, strlen (BUF); releasedc (hwnd, HDC );}

Note that Windows functions and output functions are used here, so the header files windows. h and stdio. h must be included.
In the application, add a button to call the member functions of this class:

void CCH_19_DllTestDlg::OnBtnOutput() {// TODO: Add your control notification handler code herePoint pt;pt.output(5,3);}

We can use dumpbin to check the DLL:
1 0 00001014 ?? 4point @ qaeaav0 @ abv0 @ Z
2 1 Listen 100a? Add @ yahhh @ Z
3 2 listen 100f? Output @ point @ qaexhh @ Z
4 3 00001005? Subtract @ yahhh @ Z

Where? 4point @ qaeaav0 @ abv0 @ Z is the constructor ,? In output @ point @ qaexhh @ Z, @ point indicates that it is a function of the Point class, Qae indicates that it is a public function, and X indicates that the return value type is void, HH indicates two int type parameters.

In fact, we can export only a few functions of the class instead of the entire class:

Class Point {public: void dll1_api output (int x, int y); // export this function void test ();};

The following problems are closely related to the previous problems. When the C ++ compiler generates a DLL, It will adapt the exported function name, but the rules for changing different compilers are not exactly the same, in particular, if a pure C compiler uses this DLL in sequence, functions in the DLL cannot be found due to different adapted names.
Therefore, we hope that the name of the exported function should not be changed during the compilation of the dynamic link library file. We can use extern "c" to compile the specified content in C:

#ifdef DLL1_API#else#define DLL1_API extern "C"__declspec(dllimport)#endifDLL1_API int add(int a, int b);DLL1_API int subtract(int a, int b);

#define DLL1_API extern "C"_declspec(dllexport)#include "CH_19_Dll1.h"//#include <Windows.h>#include <stdio.h>int add(int a, int b){return a + b;}int subtract(int a, int b){return a - b;}

Note that the C language is used, so you have to comment out the class-related code. Let's use dumpbin to see the DLL:
Ordinal hint RVA name

1 0 limit 100a add
2 1 00001005 subtract
At this time, the name has not been adapted.

There are also call conventions that cause name adaptation. By default, the cdecl: parameter is used to press the stack from right to left, and the consumer clears the stack. If we change it to _ stdcall: if the parameter is set from right to left and the called function clears the stack, the function name is changed:
Ordinal hint RVA name

1 0 00001005 _ add @ 8
2 1 Listen 100a _ subtract @ 8

We can use the module definition file to solve the problem of different compilers and different languages modifying functions. Create a dynamic link library and add a. cpp file to it:

int add(int a, int b){return a + b;}int subtract(int a, int b){return a - b;}

Then, add a notepad file under its directory and change the suffix to. Def. Use VC ++ to open it and add the following code:
Library ch_19_dll2

Exports
Add
Subtract

The first line is the name of the Dynamic Link Library, and the exports statement indicates the name of the function to be exported. For detailed usage, refer to msdn. In this case, the names of the exported functions are unified.

All of these are implicitly loaded. Now let's take a look at how to explicitly load the program, first look at the program:

Void cch_19_dlltestdlg: onbtnadd () {// todo: add your control notification handler code herehinstance hinst; // Load dynamic link library hinst = loadlibrary ("ch_19_dll2.dll "); typedef int (* addproc) (int A, int B); // obtain the function address addproc add = (addproc) getprocaddress (hinst, "add"); If (! Add) {MessageBox ("failed to get function address"); return;} cstring STR; Str. format ("5 + 3 = % d", add (5, 3); MessageBox (STR );}

Note: The second parameter of getprocaddress is specified by. Def.
We can see that implicit loading is easier to implement and can be directly used after loading. The display loading is more flexible and the DLL can be loaded only when needed. But the trouble is that once the new function name generated by the compiler changes, it must be modified. For example, if the function call method in the DLL is changed to stdcall, the function pointer here must also be changed to stdcall. If the DLL does not use. Def to specify the export name, you must use the name modified by the compiler :? Add @ yahhh @ Z, or use the access serial number:

ADDPROC Add = (ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1));

The access serial number can also be obtained through dumpbin.
Ordinal hint RVA name

1 0 00001005? Add @ yahhh @ Z

Of course, in actual application, it is recommended that you use a better name. After all, meaningful names are better than serial numbers.

In fact, an entry function is required for loading DLL in windows, just as the console or DOS program requires the main function and Win32 program requires the winmain function. This function is called dllmain and the declaration is as follows:
Bool winapi dllmain (hinstance hinstdll, DWORD fdwreason, lpvoid lpvreserved );
The second parameter is the reason for the call. You can use a switch/case statement to process each case separately. This function is an optional function. Because our DLL only provides some simple functions, it is not used. It should be noted that do not make too complex calls in this function. At this time, some core dynamic libraries, such as user32.dll or gdi32.dll, are not loaded yet. If the dllmain function we compile needs to call some functions of these two libraries, an error will occur.

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.