Introduction to dll in c ++ (details)

Source: Internet
Author: User
Tags types of functions

Large applications are composed of many modules that complete relatively independent functions and collaborate with each other to complete the work of the entire software system. Some modules may have common functions and will still be used when constructing other software systems. When constructing a software system, if the source code of all modules is statically compiled into the entire application EXE file, some problems will occur: one drawback is that the size of the application is increased, it occupies more disk space and consumes a large amount of memory space during program running, resulting in a waste of system resources. Another drawback is that when writing large EXE programs, all source code must be adjusted during each modification and reconstruction, which increases the complexity of the compilation process and is not conducive to periodic unit tests.
Windows provides a completely different and effective programming and running environment. You can create an independent program module as a smaller DLL (Dynamic Linkable Library) file, they can be compiled and tested separately. During runtime, the system will load the EXE program to the memory space only when it does need to call these DLL modules. This method not only reduces the size of the EXE file and the need for memory space, but also enables these DLL modules to be used by multiple applications at the same time. Windows itself implements some major system functions in the form of DLL modules.

In general, a DLL is a disk file. dll,. DRV,. FON,. SYS, and many system files with. EXE extension can be DLL. It consists of global data, service functions, and resources, and is loaded into the virtual space of the calling process by the system at runtime, becoming part of the calling process. If there is no conflict with other DLL, the file is usually mapped to the same address of the virtual space of the process. The DLL module contains various export functions to provide external services. A dll can have its own data segment but does not have its own stack. It uses the same stack mode as the application that calls it. a dll has only one instance in the memory; DLL implements code encapsulation. DLL compilation is independent of the specific programming language and compiler.

In the Win32 environment, each process copies its own read/write global variables. To share memory with other processes, you must use a memory ing file or declare a shared data segment. The stack memory required by the DLL module is allocated from the stack of the running process. When Windows loads the DLL module, it matches the process function call with the export function of the DLL file. In Windows, the DLL operation only maps the DLL to the virtual address space of the process that requires it. Any object (including variables) created by the code in the DLL function is owned by the thread or process that calls it.

Call Method

1. Static call method: the compilation system loads the DLL and the encoding of the DLL uninstallation when the application ends (if other programs use the DLL, in Windows, the Application Record of the DLL is reduced by 1 until all related programs end to use the DLL. It is simple and practical, but not flexible enough to meet general requirements.

Implicit call: You need to add the. LIB file generated when a dynamic Connection Library is generated to the project of the application. To use a function in the DLL, you only need to describe it. You do not need to call LoadLibrary () and FreeLibrary () for implicit calls (). When a programmer creates a DLL file, the link program automatically generates a corresponding LIB import file. This file contains the symbolic name and optional Identification Number of each DLL export function, but does not contain the actual code. The LIB file is compiled into the application project as an alternative DLL file.

When programmers compile and generate an application through static links, the calling functions in the application match the exported symbols in the LIB file. These symbols or identifiers enter the generated EXE file. The LIB file also contains the corresponding dl l file name (but not the full path name). The link program stores the name in the EXE file.

When a DLL file needs to be loaded while the application is running, Windows will find and load the DLL based on the information, and then use the symbolic name or identification number to achieve dynamic links to the DLL function. All DLL files called by the application will be loaded into the memory when the application EXE file is loaded. The executable program is linked to an input library file (. LIB file) that contains DLL output function information ). The operating system loads the DLL when using an executable program. The executable program calls the DLL output function directly through the function name. The Calling method is the same as its function in the program.

2. Dynamic calling method: the programmer uses API functions to load and uninstall the DLL to call the DLL. It is complicated to use, but can use the memory more effectively, is an important way to compile large-scale applications.

Explicit call: explicitly calls your dynamic Connection Library in the application using the AfxLoadLibrary provided by LoadLibrary or MFC, the file name of the dynamic Connection Library is the parameter of the above two functions, and then GetProcAddress () is used to obtain the function to be introduced. Since then, you can call the introduced function like a function defined by the application. Before exiting the application, use the AfxFreeLibrary provided by FreeLibrary or MFC to release the dynamic Connection Library. Directly call the LoadLibary function of Win32 and specify the DLL path as the parameter. LoadLibary returns the HINSTANCE parameter, which is used by the application to call the GetProcAddress function. The GetProcAddress function converts the symbolic name or identification number to the internal address of the DLL. The programmer can decide when to load or not load the DLL file, and the explicit link decides which DLL file to load at runtime. Before using the DLL program, you must load (LoadLibrary) the DLL to obtain the handle of a DLL module. Then, call the GetProcAddress function to obtain the pointer of the output function, you must uninstall the DLL (FreeLibrary) before exiting ).

Windows will follow the search order below to locate the DLL:

Directory containing the EXE file
Current working directory of the process
Windows System directory
Windows Directory
A series of directories listed in the Path environment variable
DLL in MFC

Non-mfc dll: Refers to a DLL written directly in C language without the use of the MFC class library structure. The output function generally uses the Standard C interface, it can be called by applications not compiled by MFC or MFC.
Regular DLL: similar to the following Extension DLLs, it is written in the MFC class library. Obviously, there is a class that inherits CWinApp in the source file. It can be subdivided into static connection to MFC and dynamic connection to MFC.
The dynamic connection library for static connection to MFC is only supported by the Professional Edition and Enterprise Edition of VC. The output functions in such DLL applications can be used by any Win32 program, including the applications using MFC. The input function is in the following format:

Extern "C" EXPORT YourExportedFunction ();

Without the extern "C" modifier, the output function can only be called from the C ++ code.

DLL applications are derived from CWinApp, but there is no message loop.

The output function in the DLL application that dynamically links to the MFC rule can be used by any Win32 program, including the application that uses the MFC. However, all functions output from the DLL should start with the following statement:

AFX_MANAGE_STATE (AfxGetStaticModuleState ())

This statement is used to correctly switch the status of the MFC module.

Regular DLL can be called by all applications written in languages that support DLL technology. In this dynamic connection library, it must have a class inherited from CWinApp. The DLLMain function is provided by MFC and does not need to be explicitly written by itself.

Extension DLL: Used to reuse the classes inherited from MFC. That is to say, a dynamic Connection Library of this type can be used to output a class inherited from MFC. Its output functions can only be used by applications that use MFC and dynamically link to MFC. You can inherit the classes you want from MFC that are more suitable for your use and provide them to your applications. You can also provide the object pointer of the MFC or MFC inheritance class to your application at will. Extension DLL is created using the dynamic connection version of MFC, and is called only by applications written in the MFC class library. Extension DLLs is different from Regular DLLs. It does not have class objects inherited from CWinApp. Therefore, you must add initialization code and end code for your own DLLMain function.

Compared with rule DLL:

1. It does not have an object derived from CWinApp;

2. It must have a DLLMain function;

3. When DLLMain calls the AfxInitExtensionModule function, it must check the return value of this function. If 0 is returned, DLLMmain also returns 0;

4. If you want to output a CRuntimeClass object or resource, you must provide an initialization function to create a CDynLinkLibrary object. In addition, it is necessary to output the initialization function;

5. the MFC application using extended DLL must have a class derived from CWinApp, and the extended DLL initialization function is generally called in InitInstance.

DLL entry function

1. Each DLL must have an entry point. DLLMain is a default entry function. DLLMain is responsible for initialization and termination. Whenever a new process or a new thread of the Process accesses the DLL, or every process or thread accessing the DLL no longer uses or ends, all call DLLMain. However, using TerminateProcess or TerminateThread to end a process or thread does not call DLLMain.

DLLMain function prototype:

Bool apientry DLLMain (HANDLE hModule, DWORD ul_reason_for_call, LPVOID
LpReserved)
{
Switch (ul_reason_for_call)
{
Case DLL_PROCESS_ATTACH:
.......
Case DLL_THREAD_ATTACH:
.......
Case DLL_THREAD_DETACH:
.......
Case DLL_PROCESS_DETACH:
.......
Return TRUE;
}
}

Parameters:

HMoudle: A handle that points to itself when the dynamic library is called (in fact, it is an selector pointing to the _ DGROUP segment );

Ul_reason_for_call: indicates the reason why the dynamic library is called. When a process or thread loads or unmounts a dynamic Connection Library, the operating system calls the entry function and describes the reason why the dynamic Connection Library is called. All its possible values are:

DLL_PROCESS_ATTACH: The process is called;

DLL_THREAD_ATTACH: The thread is called;

DLL_PROCESS_DETACH: the process is stopped;

DLL_THREAD_DETACH: The thread is stopped;

LpReserved: a parameter reserved by the system;

2. _ DLLMainCRTStartup

To use the DLL version (multithreading) of the "C" Runtime Library (CRT, C Run time Library), a DLL application must specify _ DLLMainCRTStartup as the entry function, the DLL initialization function must be DLLMain.

_ DLLMainCRTStartup: Data (C Runtime Data) of the "C" Runtime when the process or thread is bound to the DLL) allocate space and initialize and construct a global "C ++" object. When the process or thread terminates the use of DLL (Detach), clear the C Runtime Data and destroy the global "C ++" object. It also calls the DLLMain and RawDLLMain functions.

RawDLLMain is required when the DLL application dynamically links to the mfc dll, but it is statically linked to the DLL application. Explains the cause of status management.

Call conventions

There are two types of conventions for the dynamic library output function: The call convention and the name modification convention.

1) Call convention (Calling convention): determines the order in which function parameters are transferred to and from the stack. The caller or the caller pushes the parameter to the stack, and the modifier conventions used by the compiler to recognize function names.

There are many function call conventions. Here is a simple introduction:

1. The _ stdcall call convention is equivalent to the PASCAL call convention that is frequently used in 16-bit dynamic libraries. In 32-bit VC ++ 5.0, PASCAL's call Convention is no longer supported (in fact, it has been defined as _ stdcall. In addition to _ pascal, __fortran and _ syscall are not supported). Instead, they are replaced by the _ stdcall call convention. The two are essentially the same, that is, the function parameter is passed from right to left through the stack. The called function clears the memory stack of the transfer parameter before returning, but the difference is the function name modifier section (the modification section of the function name will be described in detail later ).

_ Stdcall is the default calling method of the Pascal program. It is usually used in Win32 API. The function uses the stack pressure method from right to left and clears the stack when it exits. After compiling a function, VC adds an underline prefix to the function name, and adds "@" and the number of bytes of the parameter to the function name.

2. C call conventions (which are described by the _ cdecl keyword) are pushed to the stack in sequence from right to left. The caller pushes the parameters to the stack. The memory stack of the transfer parameter is maintained by the caller (because of this, the function that implements the variable parameter can only use this call Convention ). In addition, the function name modification conventions are also different.

_ Cdecl is the default call Method for C and C ++ programs. Every function that calls it contains the code to clear the stack. Therefore, the size of the executable file generated is larger than that of the call to the _ stdcall function. The function uses the stack pressure mode from right to left. After compiling a function, VC adds an underline prefix to the function name. It is the default MFC call convention.

3. The _ fastcall call convention is "people" as its name. Its main feature is fast because it transmits parameters through registers (in fact, it uses ECX and EDX to transmit the first two DWORD or smaller parameters, and the remaining parameters are still transmitted from the right to the left pressure stack, the called function clears the memory stack of the transfer parameter before returning). In terms of the function name modification conventions, it is different from the previous two.

_ Fastcall functions use registers to pass parameters. After compiling a function, VC adds the "@" prefix to the function name, and adds "@" and the number of parameters after the function name.

4. thiscall is only applied to "C ++" member functions. This pointer is stored in the CX register and the parameter is pressed from right to left. Thiscall is not a keyword and cannot be specified by programmers.

5. The naked call uses the 1-4 call timing. If necessary, the compiler will generate code to save the ESI, EDI, EBX, and EBP registers when entering the function, when you exit the function, the code is generated to restore the content of these registers.

Naked call does not generate such code. The naked call is not a type modifier, so it must be used together with _ declspec.

The keywords _ stdcall, _ cdecl, and _ fastcall can be directly added before the function to be output, or in the Setting environment... select \ C/C ++ \ Code Generation. When the keywords added before the output function are different from those selected in the compiling environment, the keywords directly added before the output function are valid. Their corresponding command line parameters are/Gz,/Gd, And/Gr. The default status is/Gd, Which is _ cdecl.

To fully imitate PASCAL's call convention, you must first use the _ stdcall call Convention. As for the function name Modification Convention, you can use other methods to imitate it. Another thing worth mentioning is WINAPI macro, Windows. h supports this macro. It can translate the function into an appropriate call convention. In WIN32, it is defined as _ stdcall. You can use the WINAPI macro to create your own APIs.

2) Name modification conventions

1. Decoration name)

"C" or "C ++" functions are identified by modifier internally (Compilation and link. Modifier is a string generated by the compiler when compiling a function definition or prototype. In some cases, modifying the name of a function is necessary, for example, specifying the output "C ++" overload function, constructor, and destructor in the module definition file, for example, call the "C" or "C ++" function in the assembly code.

Modifier names are jointly determined by function names, class names, call conventions, return types, parameters, and so on.

2. The name Modification Convention varies with the call convention and the compilation type (C or C ++. The function name modification conventions vary with the compilation type and call conventions.

Rules for modifying function names during a and C Compilation:

The _ stdcall call Convention adds an underline prefix before the output function name, followed by a "@" symbol and the number of bytes of the parameter, in the format of _ functionname @ number.

The _ cdecl call Convention only adds an underline prefix before the output function name in the format of _ functionname.

_ Fastcall: Add a "@" symbol before the output function name, followed by a "@" symbol and the number of bytes of the parameter. The format is @ functionname @ number.

They do not change the case sensitivity of the output function name. This is different from PASCAL's call conventions. PASCAL's output function names are not modified and all are capitalized.

B. Conventions for function name modification during C ++ Compilation:

_ Stdcall call conventions:

1. Take "? "Mark the start of the function name, followed by the function name;

2. The parameter table starts with "@ YG" after the function name, followed by the parameter table;

3. The parameter table is represented in code:

X -- void,

D -- char,

E -- unsigned char,

F -- short,

H -- int,

I -- unsigned int,

J -- long,

K -- unsigned long,

M -- float,

N -- double,

_ N -- bool,

....

PA -- indicates the pointer. The code behind the pointer indicates the pointer type. If a pointer of the same type appears consecutively, it is replaced by "0". A "0" indicates a repetition;

4. the first item of the parameter table is the type of the return value of the function, followed by the Data Type of the parameter. the pointer ID is prior to the Data Type indicated by the parameter;

5. mark the end of the entire name with "@ Z" after the parameter table. If this function has no parameter, it ends with "Z.

The format is "? Functionname @ YG ***** @ Z "or "? Functionname @ YG * XZ ",

For example

Int Test1 (char * var1, unsigned long) ----- "? Test1 @ YGHPADK @ Z"
Void Test2 () ----- "? Test2 @ YGXXZ"

_ Cdecl:

The rules are the same as the _ stdcall call Convention above, except that the start mark of the parameter table is changed from "@ YG" to "@ YA ".

_ Fastcall:

The rules are the same as the _ stdcall call Convention above, except that the start identifier of the parameter table changes from "@ YG" to "@ YI ".

The "_ cedcl" Declaration for the function can only be called by C/C ++.

DLL Functions

The dynamic link library defines two types of functions: the export function and the internal function ). Export functions can be called by other modules. Internal functions are used within the DLL program that defines them.

The following methods are used to output functions:

1. Traditional Methods

Specify the function or variable to be input in the EXPORT section of the module definition file. The syntax format is as follows:

Entryname [= internalname] [@ ordinal [NONAME] [DATA] [PRIVATE]

Where:

Entryname is the name of the output function or data to be referenced;

Internalname is the same as entryname;

@ Ordinal indicates the sequence number (index) in the output table );

NONAME is used only when output by sequence number (entryname is not used );

DATA indicates that a DATA item is output. The program that outputs DATA using DLL must declare this DATA item as _ declspec (DLLimport ).

In the preceding items, only entryname is required, and other items can be omitted.

For a "C" function, entryname can be equivalent to the function name, but for a "C ++" function (member function, non-member function), entryname is a modifier name. You can get the modified name of the function to be output from the. map image file, or use DUMPBIN/SYMBOLS to get the modified name, and then write them in the output module of the. def file. DUMPBIN is a tool provided by VC.

If you want to output a "C ++" class, write the data to be output and the modifier of the members to the. def module definition file.

2. Output in the command line

Specify the/EXPORT command line parameter for the LINK program LINK and output the relevant functions.

3. Use the modifier _ declspec (DLLexport) provided by MFC)

Add the _ declspec (DLLexport) modifier before the declaration of the functions, classes, and data to be output to indicate the output. _ Declspec (DLLexport) removes the underline prefix of the output function name in the case of C call conventions and C compilation. Extern "C" makes it possible to use the C Compilation Method in C ++. To define a "C" function under "C ++", you need to add the extern "C" keyword. Use extern "C" to indicate that the function uses the C compiling method. The output "C" function can be called from the "C" code.

For example, a C ++ file contains the following functions:

Extern "C" {void _ declspec (DLLexport) _ cdecl Test (int var );}

The output function is named Test.

MFC provides some macros for this purpose.

AFX_CLASS_IMPORT :__ declspec (DLLexport)
AFX_API_IMPORT :__ declspec (DLLexport)
AFX_DATA_IMPORT :__ declspec (DLLexport)
AFX_CLASS_EXPORT :__ declspec (DLLexport)
AFX_API_EXPORT :__ declspec (DLLexport)
AFX_DATA_EXPORT :__ declspec (DLLexport)
AFX_EXT_CLASS: # ifdef _ AFXEXT
AFX_CLASS_EXPORT
# Else
AFX_CLASS_IMPORT
AFX_EXT_API: # ifdef _ AFXEXT
AFX_API_EXPORT
# Else
AFX_API_IMPORT
AFX_EXT_DATA: # ifdef _ AFXEXT
AFX_DATA_EXPORT
# Else
AFX_DATA_IMPORT

Macros such as AFX_EXT_CLASS, if used in the implementation of DLL applications, it indicates the output (because _ AFX_EXT is defined, it is usually specified in the identifier parameter of the compiler/D_AFX_EXT ); if it is used in an application that uses DLL, it indicates the input (_ AFX_EXT is not defined ).

To output the entire class, use _ declspec (_ DLLexpot) for the class. to output the member function of the class, use _ declspec (_ DLLexport) for the function ). For example:

Class AFX_EXT_CLASS CTextDoc: public CDocument
{
...
}
Extern "C" AFX_EXT_API void WINAPI InitMYDLL ();

Among these methods, the third method is recommended for ease of use. The second method is the first method. If output by sequence number, the call efficiency is higher. The second method is the second method.

Module definition file (. DEF)

The module definition file (. DEF) is a text file consisting of one or more module statements used to describe the DLL attributes. Each DEF file must contain at least the following module definition statements:

The first statement must be a LIBRARY statement that specifies the DLL name;
The EXPORTS statement lists the names of the exported functions. The modified names of the functions to be output are listed under EXPORTS. The names must be exactly the same as those of the defined functions, in this way, a function name without any modification is obtained.
You can use the DESCRIPTION statement to describe the usage of the DLL (optional );
";" (Optional) Comment on a row ). The relationship between the DLL program and the program that calls its output function
1. Relationship between DLL and process and thread

The DLL module is mapped to the virtual address space of the process that calls it.
The DLL Memory is allocated from the virtual address space of the calling process and can only be accessed by the thread of the process.
The DLL handle can be used by the calling process, and the call Process Handle can be used by the DLL.
DLL uses the stack of the calling process.
2. About shared data segments

The global variables defined by DLL can be accessed by the calling process; The DLL can access the global data of the calling process. Each process using the same DLL has its own DLL global variable instance. If multiple threads concurrently access the same variable, you need to use the synchronization mechanism. For a DLL variable, If you want each thread that uses the DLL to have its own value, the Local Thread storage should be used (TLS, Thread Local Strorage ).

You can add pre-compiled commands to a program or set the data segment attributes in the project settings of the development environment. these variables must be assigned with initial values. Otherwise, the compiler will place the variables without initial values in a data segment called uninitialized.

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.