My DLL (Dynamic Link Library) Learn Note Rivershan (original)

zhaozj2021-02-08  211

DLL (DYNAMIC LINK LIBRARIES) topic:

The more large applications are composed of many modules, which complete relatively independent features, which work together to complete the work of the entire software system. There may be some modules that are more common and will be used when constructing other software systems. When building a software system, if you still compile all the source code of all modules to the entire application EXE file, some issues are generated: A disadvantage is to increase the size of the application, which will take up more disk space, program operation At the time, there will be a large memory space, causing waste of system resources; another disadvantage is that when writing large EXE programs, the compilation of all source code must be adjusted at each modification, and the complexity of the compilation process is added. It is also not conducive to the phase of the unit test.

A completely different more efficient programming and operational environments on the Windows system platform, you can create a separate program module as a smaller DLL (Dynamic Linkable library) file and can be compiled and tested separately. At runtime, the system is loaded into memory space only when the exe program does call these DLL modules. This method not only reduces the size of the EXE file and the demand for memory space, but also allows these DLL modules to be used by multiple applications simultaneously. Windows yourself will implement some of the main system functions in the form of a DLL module.

In general, the DLL is a disk file, with .dll, .drv, .fon, .sys, and many system files that are .EXE can be DLL. It consists of global data, service functions, and resources, which is part of the calling process in the virtual space that is loaded into the process at runtime. If there is no conflict with other DLLs, the file is typically mapped to the same address of the process virtual space. A variety of export functions are included in the DLL module for serving the outside world. DLL can have its own data segment, but there is no own stack, use the same stack mode as the application called it; one DLL only has an instance in memory; DLL implements code encapsulation; DLL preparation and specific programming language And the compiler is independent.

In the Win32 environment, each process copies its own read / write global variables. If you want to share memory with other processes, you must use a memory map file or declare a shared data segment. The stack memory required by the DLL module is allocated from the stack of the runtime process. Windows matches the process function call with the export function of the DLL file when loading the DLL module. The Windows operating system is only in the virtual address space of the DLL to map the DLL to the virtual address space that needs it. Any objects (including variables) created in the DLL function (including variables) are homed to use its threads or processes.

First, about calling:

1, static call mode: encoding the DLL uninstalled by the compilation system completes the DLL load and the end of the application (if other programs use this DLL, Windows reduces the DLL application records until all related programs end pair When the DLL is used, it releases it), simple and practical, but not flexible enough to meet the general requirements.

Implicit call: You need to use the .lib file that generates a dynamic connection library to the application. When you want to use the function in the DLL, you only have to explain it. Implicit calls don't need to be called LoadLibrary () and FreElibrary (). When a programmer is created a DLL file, the link will automatically generate a corresponding LIB import file. This file contains the symbol name and optional identification number of each DLL export function, but does not contain actual code. The lib file is compiled into the application project as an alternate file for the DLL. When the programmer recompores an application by static link mode, the call function in the application matches the export sign in the lib file, these symbols or identification numbers enter the generated EXE file. The corresponding DLL file name (but not complete path name) is also included in the lib file, and the link is stored inside the EXE file. When the DLL file is required during the application run, Windows discovers and loads the DLL according to this information, and then dynamic links to the DLL function via the symbol name or identification number. All DLL files called by the application will be loaded in the memory when the application EXE file is loaded. The executable chain is connected to a input library file (.lib file) containing the DLL output function information. The operating system loads the DLL when loading the executable program. The executable is the same as the output function of the DLL through the function name, the calling method, and other functions inside the program, and the program. 2. Dynamic call mode: is the purpose of loading and uninstalling the DLL by the programmer with the API function to achieve the purpose of calling the DLL, which is more complicated, but can use memory more efficiently, which is an important way to prepare a large application.

Explicit call: means that the AFXLOADLibrary explicitly provided in the application is explicitly tuned by the Dynamic connection library that you do in the application, the file name of the dynamic connection library is the parameters of the above two functions, and then use GetProcAddress () Get the function you want to introduce. Since then, you can call this introduction function like using a function of using a customized function as this application. Before the application exits, the AFXFREELIBRARY to release the dynamic connection library with FREELIBRARY or MFC. Turn directly to the Win32 LoadLibary function and specify the path to the DLL as a parameter. LoadLibary returns the Hinstance parameter, the application uses this parameter when calling the getProcAddress function. The GetProcAddress function converts the symbol name or identification number to the address within the DLL. The programmer can determine when the DLL file is loaded or not loaded, and the explicit link decides which DLL file is loaded at runtime. Using a DLL program must load (loadLibrary) to load the DLL to get the handle of a DLL module, then call the getProcAddress function to get the pointer to the output function, and you must uninstall the DLL (FREELIBRARY) before exiting.

Windows will follow the search order below to locate the DLL: 1. Contains the directory of the EXE file, 2. The current working directory of the process, 3. Windows system catalog, 4. Windows directory, 5. A series of directories listed in the PATH environment variable.

Second, the DLL in the MFC:

A, NON-MFC DLL: Refers to the class library structure that does not have to be written directly with the C language. The function is generally used by the standard C interface, and can be called by the application written by non-MFC or MFC. .

B, REGULAR DLL: Like the Extension DLLs described below, it is written in the MFC class library. Obviously, there is a class inherited CWINAPP in the source file. It can also be subsequently connected to the MFC and dynamically connected to the MFC.

The dynamic connection library of static connection to the MFC is only supported by the professional and enterprise version of the VC. The output function in this class DLL application can be used by any Win32 program, including applications using MFC. The input function has the following form: Extern "C" export youRexPortedFunction (); if there is no externalN "C" modification, the output function can only be called from the C code. DLL applications derive from CWINAPP, but there is no message loop. Dynamic Link to the MFC Rule DLL Output Function The output function in the application can be used by any Win32 program, including the use of the MFC application. However, all functions output from the DLL should start with the following statement: AFX_Manage_State () This statement is used to switch the MFC module status correctly.

The Regular DLL can be called by a application written by all languages ​​that support DLL technology. In this dynamic connection library, it must have a class that inherited from cwinapp, and the DLLMAIN function is provided by the MFC without its explicit writing.

C, Extension DLL: Used to achieve the reuse of classes inherited from the MFC, that is, with this type of dynamic connection library, can be used to output a class inherited from the MFC. Its output function can only be used with MFC and dynamically link to the MFC application. You can inherit your you want from the MFC, more suitable for your own class, and provide it to your app. You can also provide you with an object pointer for MFC or MFC inherited class. The Extension DLL is created using the MFC's dynamic connection versions, and it is only called by the application written by the MFC class library. Extension DLLS and Regular DLLS are different, it does not have an object that is inherited from cwinapp, so you have to add initialization code and end code for your own DLLMAIN function.

Compared with the rule DLL, there is a difference:

1, there is no object derived from cwinapp; 2, it must have a DLLMAIN function; The CRUntimeClass type object or resource (Resources), you need to provide an initialization function to create a cdynlinklibrary object. Also, it is necessary to output the initialization function; 5, the MFC application using the extended DLL must have a class derived from the CWINAPP, and generally call the extension DLL initialization function in InitInstance.

Third, DLL entry function:

1. Each DLL must have an entry point, and DLLMAIN is a default entry function. DllMain is responsible for initialization and ending (Termination) work, whenever a new process or new thread of the process accesses the DLL, or if you have access to the DLL, you will call DLLMAIN. . However, using TerminateProcess or TerminateThread ending processes or threads without calling DLLMAIN.

DllMain the 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;}} parameter: hmoudle: It is a handle pointing to his hand when the dynamic library is called (actually, it is one of the _dgroup segments. Select); ul_reason_for_call: is a sign that illustrates the cause of the dynamic library. When a process or thread is loaded or unloaded, the operating system calls the entry function and describes the reason why the dynamic connection library is called. It is called: DLL_Process_attach: DLL_THREAD_ATTACH: thread is called; DLL_PROCESS_DETACH: The process is stopped; DLL_THREAD_DETACH: The thread is stopped; LPRESERVED: is a parameter reserved by the system.

2, _dllmaincrtstartup

In order to use the "C" CRT, C Run Time Library DLL version (multi-thread), a DLL application must specify _dllmainCrtStartup as an entry function, and the DLL initialization function must be DLLMAIN.

_DllMainCrtStartup Complete the following tasks: When the process or thread bundle (Attach) is "C" CRuntime Data) allocates space and initialization, constructs the global "C " object when the process or thread is bundled, and constructs the global "C " object, when the process or thread is terminated using the DLL (Detach When Cruntime Data is cleaned up, the global "C " object is destroyed. It also calls the Dllmain and RawdllMain functions.

RawdllMain is required when the DLL application dynamically links to the MFC DLL, but it is static link to the DLL application. The reason is explained when describing state management.

Fourth, on the agreement:

There are two conventions for dynamic library output functions: call conventions and name modifications.

1) Calling Convention: Decide the order of the stack and out of the stack when the function parameter is transmitted, and the argument is bounced by the caller or the caller, and the compiler is used to identify the modification of the function name.

The function call is agreed to have a variety, here is simple to say:

1. __ stdcall calls agreement equivalent to the PASCAL call convention used in the 16-bit dynamic library. In the 32-bit VC 5.0, the PASCAL call convention is no longer supported (in fact it has been defined as __stdcall. In addition to __pascal, __ fortran and __syscall are not supported), replaced by __stdcall call agreement. The two are substantially consistent, that is, the function's parameters pass the right left through the stack through the stack, the called function is returned to the memory stack of the transfer parameters, but the different part of the function name (about the modified part of the function name) The detailed description will be described later.

_stdcall is the default call mode of the Pascal program. It is usually used in the Win32 API. The function uses the stack of right to left, and the stack is cleared when you exit. The VC compiles the function before adding a downline prefix in front of the function name, plus the number of bytes of "@" and parameters after the function name.

2, c call convention (ie, using __cdecl keyword description) Press the parameter from right to left, and populates the argument by the caller. For the memory stack of the transfer parameters, it is maintained by the caller (for this, the function that implements variable parameters can only use the call convention). In addition, there is also different in terms of function name modification. _CDECL is the default call mode of the C and C programs. Each function that calls it contains the code that clears the stack, so the resulting executable size is larger than the call _stdcall function. The function uses the stack of right to left. VC compiles the function and adds a downline prefix in front of the function name. It is an MFC default call convention.

3, __ fastCall call agreement is "person", such as its name, its main feature is fast, because it passes the parameter through the register (actually, it uses ECX and EDX to transfer the first two double words (DWORD) or smaller The parameters, the remaining parameters are still transmitted to the left stack, the called function is returned to the internal memory stack of the transfer parameters before returning), and in terms of the function name modification, it is different from the top.

_fastCall mode functions use register pass parameters, and VC compiles the function after the "@" prefix in front of the function name, add the number of bytes of "@" and parameters after the function name.

4. ThisCall is only applied to the "C " member function. The THIS pointer is stored in the CX register, the parameter is left from right to left. Thiscall is not a keyword, so it cannot be designated by the programmer.

5, Naked Call When using 1-4 call conventions, if necessary, the compiler generates code to save the ESI, EDI, EBX, EBP registers, generate code recovery of these registers when entering the function. Naked Call does not produce such a code. Naked Call is not a type modifier, so you must use the _declspec.

Keywords __stdcall, __ cdecl, and __fastcall can be selected before the functionality of the function you want to output, or you can choose the SETTING ... / C / C / Code Generation item of the compilation environment. When the keyword before the output function is not in the compilation environment, the keyword before the output function is added directly before the output function is valid. The corresponding command line parameters are / Gz, / GD, and / GR, respectively. The default state is / gd, ie __cdecl.

To fully imitate the Pascal call, you must first use the __stdcall call convention, as for the function name modification, can be imitated by other methods. There is also a WINAPI macro, Windows.h supports this macro, which can translate the function into an appropriate call agreement, in Win32, it is defined as __stdcall. Use WinAPI macros to create your own APIS.

2) Name modification agreement

1, Decoration Name

"C" or "C " function is identified by a modified name inside (compiled and link). The modisle name is a string generated when the compiler is generated when the compile function is defined or the prototype. Some cases are necessary to use the modifier of the function, such as the output "C " overload function, constructor, the structure, the destructor, and call "C" or "C " function in the assembly code. Wait.

The modified name, class name, call agreement, return type, parameter, etc.

2, the name modification will change with the adjustment agreement and the compilation species (C or C ). The function name modification is different from the compilation species and the call agreement, and below will be explained.

A, C compile time function name modification agreement rules:

__stdcall call agreed to add a downline prefix before the output function name, and then a "@" symbol and its parameters of the number of bytes, the format is _functionName @ number. __cdecl call conventions only add a downline prefix before the output function name, format is _functionName. __Fastcall call agreed to add a "@" symbol before the output function name, the later is also a "@" symbol and its parameters, the format is @ functionName @ number.

They do not change the case sensitive in the output function name, which is different from the PASCAL call, and the function name of the Pascal agreed output without any modification and all uppercase.

B, C compile function name modification agreement rules:

__stdcall call convention: 1, with "?" identification function name, then follow the function name; 2. After the function name is labeled with the "@@ YG" identifier, the parameter table; --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 - represents a pointer, the subsequent code indicates the pointer type, if the same type of pointer continuously appears, instead of "0", a "0" represents a repetition; 4, parameter table The first item is the return value type of the function, thereafter, the data type of the parameter, the pointer identifies the end of its index; 5, after the parameter table identifies the end of the entire name, if the function No parameters, the end is ended in the "Z" identity.

The format is "? Functionname @@ yg ***** @ z" or "functionname @@ yg * xz", such as int test1 (char * var1, unsigned long) ----- "Test1 @@ yghpadk @Z "void test2 () -----"? Test2 @@ ygxxz "

__cdecl call agreement: Rule the above _stdcall call convention, just the start identification of the parameter table is changed from the "@@ YG" above "@@ ya".

__fastcall call convention: Rule the above _stdcall call convention, just the start identification of the parameter table changes from the "@@ yg" above "@@ yi".

The province of VC to the function is "__CEDCL", which will only be called by C / C . 5. Functions on the DLL:

There are two functions in the dynamic link library: export function and internal function (INTERNAL FUNCTION). The export function can be called by other modules, and the internal function is used inside the DLL program that defines their DLL programs. The method of output functions has the following:

1, traditional method

Specify functions or variables to enter in the Export section of the module definition file. The syntax format is as follows: entryName [= INTERNALNAME] [@ORDINAL [NONAME]] [Data] [private]

among them:

EntryName is the name of the output function or data being referenced;

INTERNAME with ENTRYNAME;

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

Noname is used only when outputting sequence number (no entryname);

Data indicates that the output is the data item, and the program that uses DLL output data must declare that the data item is _Declspec (dllimport).

In the above, only the entryName item is required, and others can be omitted.

For the "C" function, ENTRYNAME can be equivalent to the function name; however, for the "C " function (member function, non-member function), EntryName is a modifier. You can get a modulation name you want to output from the .map image file, or use dumpbin / symbol, 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 and members of the data to the member to the .def module definition file.

2, output in the command line

Specify the / export command line parameters for the link program LINK, and output the relevant functions.

3. Use the modified symbols provided by the MFC_Declspec (DLLEXPORT)

In the form of the function, class, data of the data to be output, add the modifier of _Declspec (dllexport), indicating the output. __DECLSPEC (DLLEXPORT) can remove the underscore prefix from the output function name in the case of C. EXTERN "C" makes it possible to use C compilation in C . Define the "C" function under "C " and you need to add the extern "C" keyword. Use extern "C" to indicate that the function uses C compile. The output "C" function can be called from the "C" code. For example, in a C file, there is a function: Extern "C" {void __declspec (dllexport) __cdecl test (int var);} The output function name is: Test MFC provides some macros, there is such a role.

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 such as macro AFX_EXT_CLASS, if the DLL for implementing the application, then the output (as defined _AFX_EXT, usually specified in the identification parameter of the compiler Option / D_AFX_ext); if used in applications used to use DLL, the input (_AFX_ext is not defined).

To output the entire class, use _DECLSPEC (_dllexpot) to class; use the member function to output the class, using _declspec (_dllexport). Such as:

Class AFX_EXT_CLASS CTEXTDOC: PUBLIC CDocument {...}

EXTERN "C" AFX_EXT_API VOID WINAPI INITMYDLL ();

In these methods, it is best to use the third, convenient to use; second is the first, if the sequence number is output, the call efficiency will be higher; the most second.

6. Modular definition file (.def)

Module definition file (.def) is a text file for one or more module statements used to describe the DLL property, each DEF file must contain at least the following module definition statement:

* The first statement must be the library statement, pointing out the name of the DLL; * The exports statement lists the name of the exported function; the function to be output is listed under Exports, this name must be exactly the same as the definition function, so Get a function name without any modification. * Use the Description statement to describe the use of the DLL (optional); * ";" comment on a row (optional).

The relationship between seven, DLL programs and programs that call their output functions

1, DLL and processes, relationships between threads

The DLL module is mapped to the virtual address space that calls its process. The memory used by the DLL is allocated from the virtual address space of the calling process, and can only be accessed by the thread of the process. The handle of the DLL can be used to use; the handle of the calling process can be used by the DLL. DLL uses the stack of the calling process.

2. About shared data segment

The global variable defined by the DLL can be called process access; the DLL can access global data of the calling process. Each process using the same DLL has its own DLL global variable instance. If multiple threads are sent to access the same variable, you need to use synchronization mechanisms; for a variable of a DLL, if you want each thread that uses the DLL, you should use the thread local storage (TLS, Thread Local Strorage).

Add a precompiled instruction to the program, or the purpose of setting the data segment attribute can also be achieved in the project settings of the development environment. You must assign these variables, otherwise the compiler will put the variables that do not assign the initial value are called Initialized data segments. Rivershan original in September 18, 2002

转载请注明原文地址:https://www.9cbs.com/read-2522.html

New Post(0)