Dynamic Link Library (DLL) generation and use

1. dynamic link library (dll) Overview

Before contacting dll not think it is very mysterious, like a black box, we can not directly run, you can not receive messages. They are some of the stand-alone file that contains an executable program or can be other dll function call to do a particular job, only the dll function call in other modules, dll just to play a role. 
In actual programming, we can accomplish a function of a function in a dynamic-link library, and then made available to other programs call. Like all of the Windows API functions are included in the dll, as Kernel32.dll, User32.dll, GDI32.dll and so on. So what good does dll?

1.1 Static and dynamic libraries

Static library: functions and data is compiled into a binary file (usually extension .lib), in the case of static library, when compiled and linked executable file, the linker copy these functions and data from a static library, and the other modules and applications are combined to create the final executable file (.exe). When the product is released only need to release the executable file does not need to publish static library is used.
DLL: When using dynamic libraries often provide two files: an import library (.lib, non-essential) and a .dll file. Here's the introduction and static libraries Although the file extension is .lib, but has a fundamentally different, for a dynamic link library, its import library file that contains the symbolic names of functions and variables derived from the dynamic library, and. dll file contains the actual dynamic library functions and data.

1.2 The benefits of using dynamic link library

You can use a variety of programming languages: For example, we can write dll with VC ++, then call it in programs written in VB.
Product enhancements: You can replace the original product by developing new dll dll, achieve the purpose of enhancing product performance. For example, we see a lot of product kicking the interface plug-in feature that allows users to dynamically change interface program, which can be achieved by replacing the interface dll.
Provide secondary development platform: users can utilize a single call dll function implemented therein, to complete other applications, to achieve the second development.
Saving memory: If multiple applications use the same dll, the dll's page into memory only once, all applications can share its pages, thus saving memory.

2. dll's created

Creating dll There are two main ways: First, using __declspec (dllexport) to create dll, the second is to create a dll using the module definition (.def) file.

2.1 Use __declspec (dllexport) to create dll

First, create a Win32 Project in VS of Visual C ++, the named Dll1. Select the DLL in the Application Type, select the Empty project in the Additional options, namely to create an empty DLL project. 

                    
 
Then add a C ++ source file project: Dll1.cpp, suppose I want to achieve is addition and subtraction, the code is as follows:

__declspec(dllexport) int add(int a, int b){
    return a + b;
}

__declspec(dllexport) int subtract(int a, int b){
    return a - b;
}

To make dll export functions, you need to add in front of each identifier needs to be exported functions: __ declspec (dllexport). 
Dll1 using the Build command generates a dynamic link library, then it will generate the .dll files and .lib files in Dll1 / Debug directory, file, these two documents is the required dynamic link library. 

                    
 
Now that you have this dll file is not in the dll you can access the add and subtract functions in other programs of it? It must be noted is this: if an application wants to access functions in a dll, then this function must have been exported functions. 
To see which derive a dll function there, Visual Studio provides a command-line tool: Dumpbin.

2.2 Dumpbin command to verify the dll exported functions

First, enter the command line to the installation directory of VS, run a batch program named VCVARS32.bat (for VS2013, the file is in the bat \ VC under the \ bin directory), the role of the file is used to create VC ++ use of environmental information. (Note that when executed VCVARS32.bat file on the command-line interface, the environment information file settings take effect only on the current command line window.) 
Then enter dumpbin command, use this command to list: 

                    
 
So you want to see a dll export functions provided in the directory Dll1.dll file, enter the following command at the command line:

dumpbin -exports Dll1.dll

                    

In the image above you can see that we derive two functions, but the name of the exported function was strange, add exported function name is "? Add @@ YAHHH @ Z" , the name subtract the export function is "? Subtrct @ @ YAHHH @ Z ". This is because when compiled and linked, C ++ tamper with the name of the function in accordance with its own rules, a process called "name mangling." This can lead to different compilers, calling dll different language problems. We therefore hope that the dynamic link library file at compile time, the name of exported functions do not change. 
To achieve this, plus the qualifier can be redefined derivation function: extern "C", such as

extern "C" __declspec(dllexport) int add(int a, int b){
//...
}

However, this approach can only solve the problem of the mutual calls between C ++ and C language function named. To solve this problem, it can be implemented by the module definition (.def) file.

2.3 module definition (.def) file creation dll

Dll file is created using def, then there is no need __declspec (dllexport), so the code is written in the most primitive way:

int add(int a, int b){
    return a + b;
}

int subtract(int a, int b){
    return a - b;
}

同时为工程创建一个后缀名为.def的文件,并添加进工程,编辑其内容为:

LIBRARY Dll1

EXPORTS
add
subtract

其中LIBRARY语句用于指定动态链接库的名称,该名称与生成的动态链接库名称一定要匹配。EXPORTS语句用于表明dll将要导出的函数,以及为这些导出函数指定的符号名。 
将该模块定义文件链接到工程中,方法为工程属性页面>链接器>输入>模块定义文件中写入“Dll1.def”。 

                    
 
然后重新Build Solution,并用dumpbin工具查看现在dll导出的函数,可以发现函数的名字改编问题得到了解决! 

                    
以上就是创建dll的两种方法,个人比较提倡使用模块定义(.def)文件创建dll,代码简洁的同时还没有名字改编的问题。 
接下来我们来看看如何使用创建好的dll。

3. dll的使用

dll的使用也有两种方法,一是隐式链接的方式加载dll,二是显示加载方式加载dll。

3.1 隐式链接方式加载dll

为了更好地展示dll的使用,我首先创建了一个基于MFC的对话框程序,然后为其添加两个按钮。 
                     
将生成好的Dll1.dll和Dll1.lib复制到对话框程序所在的文件夹,然后在CXXXDlg.h中注册动态链接库的引入库文件。因为.lib文件包含了Dll1.dll中导出函数的符号名,相当于告诉对话框程序相关函数应该去dll中调用。

#pragma comment(lib,"Dll1.lib")

然后在CXXXDlg.cpp中声明外部函数:

_declspec(dllimport) int add(int a, int b);
_declspec(dllimport) int subtract(int a, int b);

这样我们就可以使用这两个函数了。为两个按钮添加事件响应程序,并添加如下代码:

void CXXXDlg::OnBtnAdd()
{
    // TODO: Add your control notification handler code here
    CString str;
    str.Format(_T("5 + 3 = %d"), add(5, 3));
    MessageBox(str);
}

运行程序发现可以通过dll的导出函数来实现加法功能了。说明dll可以使用。 

             
3.2 显示加载方式加载dll

另一种是通过LoadLiabrary函数显示加载dll。代码如下。需要注意的是这时候我们不再需要注册.lib文件,也不需要声明外部函数。只要在需要使用的地方调用dll文件即可。

void CXXXDlg::OnBtnSubtract()
{
    // TODO: Add your control notification handler code here
    HINSTANCE hInst;
    hInst = LoadLibrary(L"Dll1.dll");
    typedef int(*SUBPROC)(int a, int b);
    SUBPROC Sub = (SUBPROC)GetProcAddress(hInst, "subtract");
    CString str;
    str.Format(_T("5-3=%d"), Sub(5, 3));
    FreeLibrary(hInst);       //LoadLibrary后要记得FreeLibrary
    MessageBox(str);
}

                    

3.3 两种加载方式对比

通过以上的例子,可以看到隐式链接和动态加载两种加载dll的方式各有优点。

隐式链接方式实现简单,一开始就把dll加载进来,在需要调用的时候直接调用即可。但是如果程序要访问十多个dll,如果都采用隐式链接方式加载他们的话,在该程序启动时,这些dll都需要被加载到内存中,并映射到调用进程的地址空间,这样将加大程序的启动时间。而且一般来说,在程序运行过程中只是在某个条件满足的情况下才需要访问某个dll中的函数,如在上述例子中,我只有在点击按钮时才需要访问dll,其他情况下并不需要访问。这样如果所有dll都被加载到内存中,资源浪费是比较严重的。
显示加载的方法则可以解决上述问题,dll只有在需要用到的时候才会被加载到内存中。另外,其实采用隐式链接方式访问dll时,在程序启动时也是通过调用LoadLibrary函数加载该进程需要的动态链接库的。
————————————————
版权声明:本文为CSDN博主「Elaine_Bao」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/elaine_bao/article/details/51784864

发布了12 篇原创文章 · 获赞 49 · 访问量 1万+

Guess you like

Origin blog.csdn.net/qq_36570733/article/details/104516798