相比于源码,动态链接库使用起来更加方便简洁,而且可以对源代码起到保护作用。
生成动态链接库
我们以vs2010为例,生成一个动态链接库,首先在VS2010中新建一个项目,选择“Win32控制台应用程序“或“Win32项目”都是可以,只要在“应用程序设置”中选择“DLL”和“空项目”就好:
然后我们分别在头文件和源文件中添加文件:
在testdll.h中添加下列内容:
#ifndef TestDll_H_
#define TestDll_H_
#ifdef MYLIBDLL
#define MYLIBDLL extern "C" _declspec(dllimport)
#else
#define MYLIBDLL extern "C" _declspec(dllexport)
#endif
MYLIBDLL int Add(int plus1, int plus2);
#endif
在testdll.cpp中添加下列内容:
#include "testDll.h"
#include <iostream>
using namespace std;
int Add(int x, int y)
{
int add_result = x + y;
return add_result;
}
生成解决方案,在工程目录下查看生成结果:
这样的话,并没有生成我们需要的lib!!!
这是因为:有了导出类和函数才会有lib,如果只有导出函数,不会生出lib
我们有两种办法解决这个问题:
(1)加上.def文件,也就是模块定义文件:
在testdll.def中添加代码:
LIBRARY testdll // 库名为testdll,省略库名即为动态链接库文件名
EXPORTS // 输出
Add @1 // 带序号的输出函数名
再次生成解决方案:
(2)新建Win32 DLL项目的时候勾选“导出符号”选项
我们重新生成工程:
完成后我们发现,编译器给我们添加好了一些东西:
这和我们上面说的情况是一样的,添加好的.h与.cpp文件中已经写好了类,所以不在需要定义.def文件。
在这里我们就不再重复这种情况下的导出过程,和第一种差不多的。
至此,动态链接库就生成好了。
调用动态链接库
既然要调用动态链接库,就用了解我们生成的东西在调用的过程中的作用。
http://blog.csdn.net/jhgameboy/article/details/23710429
大家可以参考这个博客,我也把其中重要的东西摘录到这里:
(1)lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。
(2)如果有dll文件,那么lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容;如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。使用静态编译的lib文件,在运行程序时不需要再挂动态库,缺点是导致应用程序比较大,而且失去了动态库的灵活性,发布新版本时要发布新的应用程序才行。
(3)动态链接的情况下,有两个文件:一个是LIB文件,一个是DLL文件。LIB包含被DLL导出的函数名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到DLL文件。在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中相应函数代码的地址,从而节省了内存资源。DLL和LIB文件必须随应用程序一起发行,否则应用程序会产生错误。
(4)h头文件,包含lib中说明输出的类或符号原型或数据结构。应用程序调用lib时,需要将该文件包含入应用程序的源文件中。
所以在使用动态链接库时,其实需要三个文件:
(1).h头文件,包含dll中说明输出的类或符号原型或数据结构的.h文件。应用程序调用dll时,需要将该文件包含入应用程序的源文件中。
(2).LIB文件,是dll在编译、链接成功之后生成的文件,作用是当其他应用程序调用dll时,需要将该文件引入应用程序,否则产生错误。
(3).dll文件,真正的可执行文件,开发成功后的应用程序在发布时,只需要有.exe文件和.dll文件,并不需要.lib文件和.h头文件。
新建一个Win32控制台程序,将用于生成动态链接库的testdll.h加入到工程,并新建一个.cpp文件:
testdll.h中已经有代码了,在main.cpp中添加:
#include "testdll.h"
#include <iostream>
using namespace std;
int main()
{
cout<<Add(5,2)<<endl;
getchar();
return 0;
}
为了再具体的说明下这三个文件的作用,我们按步骤测试下他们的作用,现在我们只用到了.h文件,直接编译。
程序报错:
在Add函数中转到定义,可以查看到该函数的定义:
这就是.h文件的作用,定义了函数的结构,但是由于没有库文件,编译无法通过。
加入库文件
附加库目录添加库的路径:
附加依赖项添加库的名称:
再次编译,可以通过,编译成功就不截图了,太占地方了,通过后运行程序:
这就是缺少dll文件的错误提醒,因为dll文件才是真正的可执行文件。
加入dll
其实我们可以直接把dll文件放进工程文件的程序所在的目录内,这样不再需要配置任何东西就可以直接运行。