In-depth understanding of dynamic library
First, the purpose of dynamic connection library, Dynamic-Link Libraries (DLL) is a software technology provided by Microsoft. It is essentially an executable module containing some functions and data, which can be called by the application (.exe) or other DLL. This technology has the following benefits: sharing resources, saving memory, support multi-language, reusable, easy to develop, etc. This is said that it is a bit old set, it is also, the textbook is. Cough, just review your homework .... Let's talk about my understanding. There is no summary without a summary. This seems to listen to who said. As a carrier, it is used to summarize the past experience, and the dynamic library is unique. For example, you have accumulated a lot of experience, skills, ideas (?) And professional information in previous project development or programming, and they are valuable in specific fields. But with the development of development, the implementation platform upgrades, these experiences, skills and materials may be discarded. In fact, as a summary of the previous labor results, gathered into a specific dynamic library, and it is a method of two all its beauty. Since the dynamic library has nothing to do with the programming language, the resources thus obtained can be applied more widely. As a long-standing consideration, the reuse of resources not only does not make past labor waste, but also makes the original labor value more effectively. In particular, the resource repeated utilization problem, if systematically considering software multiplexing, it is a solution and method for solving the problem of labor issues in software development. Based on existing work, fully utilize the knowledge and experience accumulated in the past application system development, the focus of development is concentrated on the application's unique constituent component, eliminating repeated labor, avoiding re-developing mistakes, thus improving software development Efficiency and quality. In addition, as a special case of mixing programming, the dynamic library is not allowed. Because the dynamic library has nothing to do with the specific programming language, as long as this language supports dynamic library technology, this language can be used, and the purpose is only one "extraction". The existence of various programming languages is because they have their own strengths. We can divide a large task into a sub-task through a dynamic library, which can be implemented by different languages, respectively. There is also a most successful example: Microsoft's application interface API. Second, there are two conventions about the dynamic connection library on dynamic library output functions: call conventions and name modifications. The call agreement determines the order of the stack and out of the stack when the function parameter is transmitted, and the compiler is used to identify the modification of the function name. Name modification changes with the adjustment agreement and compilation species (C or C ) variations. In order to allow different programming languages to share dynamic libraries, the function output must use the correct call agreement, and it is best not to have any name modifications generated by the compiler. Here are VC5 and VB5 as an example to explain how to implement these requirements in conjunction with specific situations.
(1) Call the conventions of the function call for support for VC 5.0, there are many, only the following three types: __ stdcall call agreement, C call agreement and __fastcall call agreement. __Stdcall call agreation is equivalent to a 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. C call conventions (ie, using __cdecl keyword description) and __stdcall call conventions are different, although the parameter transmission is the same, but the memory stack for transmitting parameters is maintained by the caller (because of this, because of this. Functions that implement variable parameters can only use this call approach), in addition, there is also different in terms of function name modification. __fastcall call agreement is "person", such as its name, its main feature is fast, because it passes the parameters through the register (actually, it transmits the first two double characters or smaller parameters with ECX and EDX, the rest The parameter is still in the right to left, and the called function is returned to the memory stack of the transfer parameters before returning), which is different from the first two in terms of function name modification. 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. By the way, it is necessary to fully imitate the PASCAL call. First, the __stdcall call convention must be used. As for the function name modification, it can be imitated by other methods. There is also a WINAPI macro, Windows.h supports the macro, which can translate the output function into an appropriate call agreement, in Win32, it is defined as __stdcall.
Recommendation: Use WinApi macro so you can create your own APIS.
(2) Function Name Modifying Convention Function Name Modification Different from the compilation species and call agreement, the following will be explained.
For C compile, __ stdcall call conventions plus a downline prefix before the output function name, add a "@" symbol and its parameters, 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 sense case 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. Speaking here, I give a method that completely imitates the approximation of the PASCAL call, and is achieved by aliasing in the. DEF file. For example: int __stdcall myfunc (int A, double b); void __stdcall initcode (void); in the .def file: exports myfunc = _MYFUNC @ 12 initcode = _initcode @ 0c compilation and output function name is more complex, VC 5.0 There is no explanation in a random document. After some experiments and exploration, I found the C compile time function name modification, and now explain the following.
__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, instead of "0", a "0" represents a repetition; 4, parameters The first item of the table is the type of return value of the function, and then sequentially uses the data type of the parameter; 5, after the parameter table identifies the end of the entire name with "@z", if the function is not parameted, then "z" ID end.
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 above" @@ yg "@@ @@ YG" @YA.
__fastcall call the agreement rule to the above _stdcall call convention, just the beginning identification of the parameter table changes from the "@@ yg" above "@@ yi".
(3) Using __Declspec (dllexport) when there is no modified function name VC output function, and no longer uses _export modifies. __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 to compile in C , in a C file, with externaln "c" to indicate that the function uses C compile. 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
For convenience, you can use the following pre-processing statement:
#if Defined (__ cplusplus) Extern "C" {#ENDIF
// Function prototype
#if defined (__ cplusplus)} #ENDIF
In this way, through the top of the special treatment, no matter whether there is no modified function name in C .
Next, another way is introduced: do not use the __declspec (dllexPort) to modify the word output function, and use the .def file to output a function. The function to the output to be output is listed under Exports. This name must be exactly the same as the name of the definition function, so you get a function name without any modification.
At this point, we have at least three ways to get "no modified function name". I mentioned the "Function Output" when I started "" It is best not to have any name modifications generated by the compiler ", which is especially important in the multilingual mixing programming. (4) Being an experiment, an experiment is to deepen the impression of the above introduction. Experimental envision: There is such a software system, designing its interface with VB5, writing a dynamic library with VC5, used to perform some cumbersome calculations, there are some intermediate results to make simple display during the calculation process, we use VB5 to complete Display the task, then a display function is defined in VB5, callback it by a dynamic library, and calculating the calculation results as a parameter at the callback ....
First write the interface with the VB5 and define the display function. Create a new project, add a module file, define our display function (ie the callback function) in this module file: Public Sub ShowResult (Result as long) Form1.print Result 'simple simulation showing End Sub In addition, give a dynamic Description of the library output function: Declare Sub testshow lib "Test32.dll" (Byval Show as a ", put a command button on the form and add the following code: Private submmand1_click () Dim i as long testshow Addressof ShowResult, i End Sub Now uses VC5 to write our dynamic library. Create a new project. Select New Projects | Win32 Dynamic-Link Library, and enter the project name test32; then add the following to .cpp file: #include
Bool WinAPI DLLENTRYPOINT (Hinstance Hinstdll, DWord FDWRREASON, LPVOID PLVRESERVED) {Return 1; // Indicate That The DLL WAS INITIZED SUCCESSFULLY.}
Void testshow (int AppShow (int = 0; I <10; i ) {* flag = 11011 i; file: / / For simplicity, here is directly assigned " Complex Computing "APPSHOW (FLAG); File: // Tune}}
Here, use the .def file output function. Add the following to the .def file: library test32 description 'test32.dll'
Exports TestShow @ 1
Set the call to __stdcall, build TEST32.DLL, copy it into the system directory. Finally, run the VB5 item written above. OK? !
Experiment 1: Call the call to the default setting, ie C call convention, other constant, recombine to generate TEST32.DLL and copy it into the system directory, try to take a VB5 project ......
Experiment 2: Call the call to default to the default setting, ie the C call convention, add __stdcall keyword or WinAPI macro before the top of the testshow function, other constipation, recompile generation TEST32.DLL and copy it into the system directory , Try to run the VB5 project ...
Experiment 3: Call the call to default to default settings, that is, c call conventions, add __stdcall keywords or WinAPI macros before the above TestShow function, and plus __stdcall keywords before its first parameter appshow, other Not change, ie
Void __stdcall testshow (int __stddcall appswshow (int *) recompiled to generate TEST32.DLL and copy it into the system directory, try to run the VB5 project ... Tip: VB5 function call follow the API Call the agreement (__stdcall, that is, the original PASCAL).
Please refer to the relevant books for the concept and agreement of the callback function.
Third, the parameter passed on the parameters of the output function of the Win32 dynamic library have also said it, which is mainly described in further detail here. In a 32-bit dynamic library, all parameters are extended to 32 bits (such as character type parameters, short integer parameters), reverse the stack from right to left. The return value of the function is also extended to 32 bits. In the EAX register, the 8-byte return value is placed in the EDX: EAX register pair, and the return value returns to the pointer to the invisible return structure when the return value is a larger structure. When a function is used to some relevant registers (such as ESI, EDI, EBX, and EBP), the compiler automatically generates a function head and a function tail for saving and restoring these registers. The following example describes the case of parameters. We already know that __ stdcall and __cdecl calls agreed parameters are the same, and __ fastcall call agreements are different.
Void Myfunc (Char C, Short S, INT I, DOUBLE F);.. Void Myfunc (CHAR C, SHORT S, INT I, DOUBLE F) {...}............ 8192, 2.1418);
It will be like this: __stdcall and __cdecl call agreement
Position Stack ESP 0x14 2.1418 ESP 0x10 ESP 0x0C 8192 ESP 0x08 22 ESP 0x04 A ESP Return Value
__fastcall call agreement
Position Stack ESP 0x0C 2.1418 ESP 0x08 ESP 0x04 8192 ESP Return Value ECX A EDX 22
IV. The stack has been mentioned in front of the different calls to the stack of the stack in front of the transmission parameters. Here, you will focus on how different calls are agreed to maintain the normal operation of the stack, and it is also more deeply understood that the importance of maintaining the same invoking agreement. We already know that all three calls mentioned above are all right-to-left, and the motion of the stack here is done by the caller. When the call starts, the caller is controlled, it can operate on the register, while the call is ended, the caller is lost, the caller is reaches control, and it expects that some register it uses to recover its call. The state of the front, especially the stack pointer, which involves the maintenance problem of the stack. The front mention __stdcall and __fastcall call conventions are called the function to return the memory stack of the transfer parameter before returning, and the __cdecl call convention is a stack for transmitting parameters by the caller. The following example will be explained. Void myfunc1 (int C);. Void myfunc2 () {INT i = 1; .... myfunc1 (i); ....}
Let's take a look at the implementation of MyFunc2: 1, __ stdcall and __fastcall call conventions .... MOV EAX, DWORD PTR [I] Push Eax Call @ ilt 445 (? Myfunc1 @@ ygxh @ z) (0x014a11bd) // Call The end stack pointer has recovered, and the called by the caller is restored before returning .... 2, __ cdecl calls agreement ... MOV EAX, DWORD PTR [I] Push Eax Call @ ilt 30 (? Myfunc1 @@ yaxh @ Z) (0x014a101e) // Call the end stack pointer unrecovered add ESP, 4 // caller self-recovery stack pointer ....
Now I will go back and look at the experimental experiments in front. Since VB5 supports the standard API call agreement, the experiment is normally passed when the __stdcall call agreement is compiled. When the dynamic library is compiled with the __cdecl call, the experimental one and the experiment 2 can explain the problem, in fact, due to the uniform invoking, the stack used to transmit parameters has been destroyed, the phenomenon is work unusual. Although the experiment three is still compiled with __cdecl, __stdcall before the function is really a truly call agreement, so it passed smoothly.
V. Summary and Supplement The above combined experiment describes several key points of dynamic library technology: call conventions (or calling agreements), name modification, stack and parameter transmission, etc. The purpose is to use this technology to better understand the technology more deeply.