http://www.microsoft.com/china/community/program/originalarticles/techdoc/dll.mspx
Introduction to the DLL DLL Entry Function in the MFC About the Confusion Authors of the Program of the Device (.def) DLL program and the program that calls its output functions
introduction
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.
Call mode
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. Contents containing the exe file
2. Current work catalog of the process
3. Windows system catalog
4. Windows catalog
5. A series of directories listed in the PATH environment variable
DLL in 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 extern "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 (AFXGETSTATICModuleState ())
This statement is used to correctly switch the MFC module status.
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, it doesn't have an object derived from cwinapp;
2, it must have a DLLMAIN function;
3, DLLMAIN calls the AFXINITEXTENSIONMODULE function, must check the return value of the function, if it returns 0, DLLMMAIN also returns 0;
4. If it wants to output a CRUNTIMECLASS type object or resource (Resources), you need to provide an initialization function to create a CDynlinkLibrary object. And, it is necessary to output the initialization function;
5. The MFC application using extended DLL must have a class derived from the CWINAPP, and the initialization function of the extended DLL is generally called in InitInstance.
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's 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: It is a handle that is passed when the dynamic library is called (actually, it is a selector pointing to the _dgroup segment);
UL_REASON_FOR_CALL: is a logo that describes 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. All possible values are:
DLL_PROCESS_ATTACH: The process is called;
DLL_THREAD_ATTACH: Thread is called;
DLL_PROCESS_DETACH: The process is stopped;
DLL_THREAD_DETACH: The thread is stopped;
LPRESERVED: It is a parameter that is 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 adjusts
Use the dllmain and the rawdllmain function.
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.
About 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. In some cases, the name of the function is used is necessary. If you specify the output "C " overload function, constructor, the destructive function, and adjust the compilation code
Use "C" or "C " function, etc.
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. Taking the beginning of the "?" Identification function name, then follow the function name;
2, the function name is behind the "@@ YG" identifies the beginning of the parameter table, and then following the parameter table;
3, the parameter table is indicated by 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 - represents the pointer, the subsequent code indicates the pointer type, if the same type of pointer continuously, instead of "0", a "0" represents a repetition;
4, the first item of the parameter table is the return value type of the function, and then the data type of the parameter is subsequently, the pointer identifies before its index data;
5. After the parameter table identifies the end of the entire name, if the function is not parameters, the "z" identifier ends.
The format is "? Functionname @@ yg ***** @@ yg * xz", for example
Int test1 (char * var1, unsigned long) ----- "? test1 @@ yghpadk @ z"
Void Test2 () ----- "? test2 @@ ygxxz"
__cdecl call convention:
The rule is the same as the above _stdcall call, but the start identification of the parameter table is changed from the "@@ yg" above "@@ ya".
__fastcall call convention:
The rule is the above _stdcall call convention, but the beginning identification of the parameter table is changed from the "@@ yg" above "@@ yi".
The province of VC to the function is "__CEDCL", which will only be called by C / C .
Function about 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 [= INTERNAME] [@ORDINAL [NONAME]] [Data] [private]
among them:
EntryName is the name of the output function or data being referenced;
INTERNAME with ENTRYNAME;
@ordinal represents the sequence number (index) in the output table; Noname is used only when the sequence number is output (not using 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 "C" function under "C ",
Need to add Extern "C" keywords. 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);}
Its 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
Macro like AFX_EXT_CLASS, if used in the implementation of the DLL application, indicates the output (because _afx_ext is defined, it is usually specified in the identity parameter of the compiler to specify this option / D_AFX_ext); if used to use the DLL application In, the input is indicated (_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.
Module 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 a library statement, pointing out the name of the DLL;
* The exports statement lists the name of the exported function; the function to the function to be output is listed under Exports, this
A name must be exactly the same as the name of the definition function, so get a function name without any modification.
* Use the Description statement to describe the use of DLL (optional);
* ";" Comment on a row (optional).
The relationship between the DLL program and the program that calls its output function
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.
Author
Jiangshan November 7, 2002