文章目录
一、动态库和静态库
1.两者区别
静态库:在链接步骤中,连接器将库文件取得所需的代码,复制到生成的可执行文件中,这种库叫做静态库,其特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝。即静态库中的指令全部被直接包含在最终生成的exe文件中。在vs中新建生成静态库的工程,编译生成成功后,只产生一个.lib文件。
动态库:动态库链接是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行的文件,动态库提供一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个DLL中,该DLL中包含一个或者多个已经被编译,链接并使用它们的进程分开存储的函数,在vs中新建生成动态库的工程,编译成功后,产生一个.lib和一个.dll文件。
静态库的lib:该lib包含函数的代码本身(包括函数的索引,也包括实现),在编译的时候将代码加入程序当中,程序运行的时候不需要该静态库
动态库的lib:该lib包含了函数所在的DLL文件和文件中函数位置的信息,函数实现代码由运行的时候加载在进程空间中DLL提供,总之,lib是编译的时候用到的,如果完成源代码的编译,只需要lib,如果要使得动态库的程序运行起来,只需要dll
2.两者特点和使用场景
静态库特点:
静态库对函数库的链接是放在编译期完成的,程序在运行的时候与函数库再无瓜葛,移植方便。
缺点:浪费空间与资源,因为所有相关的目标文件与牵扯到的函数库会被合成一个可执行的文件。
是静态库对程序的更新,部署和发布会带来麻烦,如果静态库更新,所有使用它的应用程序程序都需要重新编译,发布给用户。
动态库特点:
动态库把一些库函数的链接载入推迟到程序运行的时期,可以实现进程之间的资源共享。
将实现进程之间的资源共享,将一些程序升级变得简单。甚至可以真正做到链接载入完全由程序代码中控制(显示调用)
二、创建动态库
1. 创建dll工程
2. 删除多余文件
代码如下:
//MyDll.h 头文件
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
// 此类是从 MyDll.dll 导出的
class MYDLL_API CMyDll {
public:
CMyDll();
// TODO: 在此添加您的方法。
void testFunc();
};
extern MYDLL_API int nMyDll;
MYDLL_API int fnMyDll(const int& i);
// MyDll.cpp : 定义 DLL 应用程序的导出函数。
//
#include "MyDll.h"
#include <iostream>
// 这是导出变量的一个示例
MYDLL_API int nMyDll=0;
// 这是导出函数的一个示例。
MYDLL_API int fnMyDll(const int& i)
{
std::cout << "fnMyDll" << std::endl;
return i;
}
MYDLL_API void commonFunc()
{
std::cout << "fnMyDll commonFunc" << std::endl;
}
// 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 MyDll.h
CMyDll::CMyDll()
{
return;
}
3. 指定dll库文件输出路径
$(SolutionDir) — 解决方案目录
$(Platform) — 平台目录(x86/x64)
$(Configuration) — 编译模式(Debug/Release)
4. 指定lib文件输出路径
dll文件是函数的实现,lib文件是函数的声明
5. 配置编译后自动拷贝头文件
目标文件夹需要预先创建,编译后自动拷贝头文件
6. 编译
在解决方案目录下生成bin和lib目录
三、使用动态库
1、在当前解决方案,添加一个win32工程,修改输出目录和上面的dll为一个路径,这样就不用拷贝dll文件到exe生成路径
添加头文件路径
1. 直接在代码中引用库文件
#include "MyDll.h"
#include <iostream>
using namespace std;
#pragma comment(lib,"..\\lib\\Win32\\Debug\\MyDll.lib")
int main() {
cout << fnMyDll(5) << endl;
}
2. 通过配置工程属性来使用dll库
工程—属性—配置属性—链接器—常规—附加库目录:加上lib文件存放目录
然后添加工程引用的lib文件名:工程—属性—配置属性—链接器—输入—附加依赖项:加上lib文件名
#include "MyDll.h"
#include <iostream>
using namespace std;
int main() {
cout << fnMyDll(5) << endl;
getchar();
}
四、创建静态库
1. 创建lib工程
创建静态库工程和动态库工程一样
2. 新建lib文件
新建的lib工程里面是空的,需要自己创建文件,示例源码如下:
// MyLib.h
class CMyLib {
public:
CMyLib();
// TODO: 在此添加您的方法。
void testFunc();
};
extern int nMyLib;
int fnMyLib(const int& i);
int nMyLib = 0;
int fnMyLib(const int& i)
{
std::cout << "fnMyLib" << std::endl;
return i;
}
// 有关类定义的信息,请参阅 MyLib.h
CMyLib::CMyLib()
{
return;
}
void CMyLib::testFunc()
{
std::cout << "CMyLib::testFunc" << std::endl;
}
3.指定lib文件输出路径
参照dll配置如下:
$(SolutionDir)bin$(Platform)$(Configuration)\
4.配置编译后自动拷贝头文件
xcopy /Y /S $(SolutionDir)MyLib*.h $(SolutionDir)include
5.编译
编译之后在输出路径能看到对应的lib文件
五、使用静态库
1.添加头文件路径
2. 添加链接依赖项和路径
六、静态库和动态库使用注意
1.Dll.A依赖Lib.B,Dll.A和Lib.B能否定义一个同名函数?
答案:不同命名空间的同名函数可以,如果是全局同名函数则不可以
我们可以在上面的dll和lib中定义一个同名的函数
void commonFunc();
然后在dll的工程中依赖lib,编译,会有提示重定义
我们在lib中加上命名空间,再次就可以编译通过