Link Library dynamic link library details

Source: Internet
Author: User
Tags export class import database

In windows, the link library is divided into two types: static Link Library. lib and dynamic link library. dll. When a dynamic link library is used, a dynamic link library is usually provided. lib is called the import database. It mainly provides the function and symbol name exported by the Dll, so that the corresponding function ing in the dll can be found during the link.
The static library and the dynamic library share similar functions. They are resources provided to other programs for calling. The call methods of the dynamic link library are divided into implicit call (static import call) and display call (dynamic import call ).

Compiling environment:
Microsoft Visual Stdio 2010
--------------------------------------------------------------------------------
DLL export symbol
For example, first generate a dll1.dll and dll1.libCopy codeThe Code is as follows: // DLL1 project, dll1.cpp
// _ Declspec (dllexport) is the export symbol
_ Declspec (dllexport) int add (int a, int B)
{
Return a + B;
}

Use Microsoft's depends tool to view dll1.dll. The exported symbols are as follows:

The meaning of each field: Ordinal (symbol number, the value referenced when GetProcAddress is used later), Hint (I am not very clear about this, it is said that I do not need to know ), function (this is the symbol name after Function export), EntryPoint (this is the address of the Function in DLL ).
Here, the function name becomes like this, because the C ++ compiler uses the C ++ Method for compilation by default. Because C ++ supports overloading, you need to add additional symbols to the function name, to distinguish it from an overloaded function with the same name.
Here we can do a simple test. The following figure shows the new console test project DllTest.Copy codeThe Code is as follows: // DllTest project, DllTest. cpp
# Include <iostream>
Using namespace std;
Int main (void)
{
// Extern int add (int a, int B );
// _ Declspec (dllimport) is an import declaration. This method is more effective than the preceding method, and the compiler can compile more efficient code.
_ Declspec (dllimport) int add (int a, int B );
Cout <add (1, 2) <endl;
Getchar ();
Return 0;
}

Compile the link and prompt the link error LNK2019: unresolved external symbol "_ declspec (dllimport) int cdecl add (int, int)" (_ imp _? Add @ YAHHH @ Z) referenced in function _ main. It is obvious that the compiler renamed the add function during compilation, and it is the same as the one viewed in depends. The definition of this symbol is not found.

After adding the code, follow these steps: (Note that the output directories of both projects are under the same debug directory as the solution. To avoid re-copying the lib file for each modification, directly use the relative path declaration .)Copy codeThe Code is as follows: // DllTest project, DllTest. cpp
# Include <iostream>
Using namespace std;
# Pragma comment (lib, "../debug/dll1.lib") // The display Declaration must be linked to dll1.lib, which is called implicitly.
Int main (void)
{
// Extern int add (int a, int B );
// _ Declspec (dllimport) is an import declaration. This method is more effective than the preceding method, and the compiler can compile more efficient code.
_ Declspec (dllimport) int add (int a, int B );
Cout <add (1, 2) <endl;
Getchar ();
Return 0;
}

After compilation and operation, use the dependstool to view the input information of dlltest.exe dependencies as follows:

As you can see, dlltest.exe introduces the dependency on dll1.dll through dll1.lib.

--------------------------------------------------------------------------------

Header file provided by DLL
Normally, when we get a. dll, we cannot know which function calls it provides (precisely, it should be the call method. Because we can use the depends tool to view the dll exported functions and their serial numbers. Of course, there may be other ways to know how to use them, but we certainly cannot know the specific internal implementation details .), Therefore, for ease of use, A. H file of the dll is usually provided to declare the method and description provided to the client. The client uses this header file to import the interfaces used. However, to avoid the declaration of these functions in many places, all interfaces are usually imported directly on the client in the. h file, and used as an export during Dll compilation. The method is as follows:Copy codeThe Code is as follows: // DLL1 project, dll1.h
# Ifndef DLL1_API
# Define dllsort api _ declspec (dllimport)
# Endif
// The code above indicates that if the dllw.api macro is not defined before the header file is included, all subsequent dllw.api macros are expanded to _ declspec (dllimport), that is, the import.
// Generally, the client does not define this macro (assuming that this macro is not defined by other files on the client). Therefore, the client uses this header file for import.
Dllbench API int add (int a, int B );

Copy codeThe Code is as follows: // DLL1 project, dll1.cpp
# Define DLL1_API _ declspec (dllexport)
// Note that before the header file is included, the DLL1_API macro is defined so that the DLL1_API in the header file is expanded to _ declspec (dllexport), and the function is declared as exported.
# Include "dll1.h"
// Export the declared function in the header file, so you do not need to declare the function again.
Int add (int a, int B)
{
Return a + B;
}

Correspondingly, after the TestDll project contains a. h file, you do not need to declare it again.Copy codeThe Code is as follows: // DllTest project, DllTest. cpp
# Include <iostream>
Using namespace std;
# Include "../dll1/dll1.h" // after this header file is included, you do not need to specify it later.
# Pragma comment (lib, "../debug/dll1.lib") // The display Declaration must be linked to dll1.lib, which is called implicitly.
Int main (void)
{
Cout <add (1, 2) <endl;
Getchar ();
Return 0;
}

The above explains why there is usually a header file when a dll is referenced, and there are a lot of stuff like # ifndef in the header file.

--------------------------------------------------------------------------------
Dynamic Link Library export class
Of course, the dynamic link library can also export classes. Note that the declared method is class DLL1_API CSample, rather than DLL1_API class CSample.
At the same time, you must note that all member functions of the exported class have been exported, but the access permission restrictions of the class member variables are still observed.
If you export the member functions of the class separately (The Declaration method is the same as that of the global function), you can instantiate the class object on the client and call the exported member functions, you cannot call member functions that are not exported (even public ).

--------------------------------------------------------------------------------
Modified symbol name
When exporting symbols, C ++ adapted the function name to support function overloading. There will be a problem. If the unused C ++ compiler is used (resulting in different compiled Symbol names) or the client uses the C compiler for calling, a link error such as LNK2019 will occur, the symbol cannot be found. This problem greatly limits the scope of DLL usage.
Solution 1:
The predeclaration using the extern "C" (note that this C must be capitalized) indicates that the function compiles the link in C mode. The function compiled in C mode to connect and export does not adapt the symbol name, so the above problem can be avoided.Copy codeThe Code is as follows: // DLL1 project, dll1.h
# Ifndef DLL1_API
# Define dllsort API extern "C" _ declspec (dllimport)
# Endif
// The code above indicates that if the dllw.api macro is not defined before the header file is included, all subsequent dllw.api macros are expanded to _ declspec (dllimport), that is, the import.
// Generally, the client does not define this macro (assuming that this macro is not defined by other files on the client). Therefore, the client uses this header file for import.
Dllbench API int add (int a, int B );
// Class CSample
//{
// Public:
// Dlliterator API int substract (int a, int B); // In this case, the exported class member function cannot be compiled
//};

Note that extern "C" must be added to both. h and. cpp, so that both the import and export are compiled in C mode.Copy codeThe Code is as follows: // DLL1 project, dll1.cpp
# Define DLL1_API extern "C" _ declspec (dllexport)
// Note that before the header file is included, the DLL1_API macro is defined so that the DLL1_API in the header file is expanded to _ declspec (dllexport), and the function is declared as exported.
# Include "dll1.h"
// Export the declared function in the header file, so you do not need to declare the function again.
Int add (int a, int B)
{
Return a + B;
}
//
// Int CSample: substract (int a, int B)
//{
// Return a-B;
//}

Then use depends to view the information:

The exported function symbol is the same as the function declaration. When the client uses the extern "C" method, the client also uses the original function name symbol when compiling the link.
It is shown that the C ++ class and member functions cannot be exported due to the C compilation link method.
In addition, if we add a standard call convention to the function declaration: DLL1_API int _ stdcall add (int a, int B); (Note that _ stdcall must be added to the function definition ). Then, use depends to view the compiled result with the symbol name _ add @ 8, which means the symbol name is changed again.
Solution 2:
Use the module definition file. def. For the format specification of this file, view MSDN and search for. def. The "LIBRARY" command is used to name the def file for export and the "EXPORTS" command is used to export the function symbol name. That is to say, the. def file is mainly used to control the exported symbols and other information.Copy codeThe Code is as follows: LIBRARY dll1
EXPORTS
Add11 = add

The alias for the add function is add11. in the H file, declare add as add11 (the function is provided to the client. Of course, you can also directly declare the function as add11 on the client, provided that you know the definition of the function ). Once. def is provided, any call Convention provided in. cpp will no longer take effect because. def specifies the generated symbol name. Here, you only need to understand that. def controls the Dll export symbol. When using the client, you only need to provide the Declaration and link the. lib file to use it.
In addition, all ides after VC6.0 must specify the. def file in the module define file in the input-> module of the LINK option (LINK) before the compiler can use the. def file.

Note:
I am still confused about the call conventions and the addition of extern "C. After learning about this, I will try again here. You are welcome to provide me with a better introduction.

--------------------------------------------------------------------------------
Show Link (dynamic import link)
As mentioned above, how can the client call the exported function without a name. You can use ordinal in the symbol table (you can view it using a tool). Of course, you can also use the function name for import. The lib file and. h file are not required for dynamic import (if you know the function name ).Copy codeThe Code is as follows: // DllTest project, DllTest. cpp
# Include <iostream>
Using namespace std;
# Include <windows. h>
Int main (void)
{
HMODULE hModule =: LoadLibraryA ("dll1.dll ");
If (NULL! = HModule)
{
Typedef int (* ADDPROC) (int a, int B );
// ADDPROC add = (ADDPROC): GetProcAddress (hModule, "add11"); // import by function name
ADDPROC add = (ADDPROC): GetProcAddress (hModule, MAKEINTRESOURCEA (1); // import the value through ordinal. Note that the second parameter must be set to a low byte value, for more information, see the MSDN description.
If (NULL! = Add)
Cout <add (1, 1) <endl;
: FreeLibrary (hModule );
}
Getchar ();
Return 0;
}

It is worth mentioning that during the dynamic import Based on the function name, it is actually based on the symbol name, that is, the symbolic name provided by the dll should be consistent with the function declaration provided to the user.

In this case, when the dynamic mode is imported to the dynamic chain, you cannot view the required input information in the. exe file.

--------------------------------------------------------------------------------
Postscript
The first time I wrote such a detailed and long blog post, I can see that it was getting rough when I wrote it later. Because when I wrote it later, I had no idea what to write, because if I expanded it, there would be too many things to add. At the same time, there are also some reasons that I do not fully understand the following content, and I am rarely using it at the same time. In short, this will make my mind quite messy. I would like to express my deep admiration for those who write blogs.

Finally, I want to declare that these are all summarized by myself by referring to the video. There must be something unprofessional or even wrong. Please give me some guidance. After learning and understanding, will be modified in time. Thank you.

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.