动态库与静态库
静态库
在链接阶段,与目标文件.o一起生成可执行文件。后续此库就消失了。
优点:可执行文件依赖少;执行期间代码装载快
缺点:可执行文件大;造成多余的副本;升级不方便,需要重新编译
动态库
在运行时才被加载,与可执行文件是分开的。
优点:动态库可实现与进程间资源共享,有一份就行;升级方便,不需要重新编译,体积小
缺点:增加可执行文件的依赖性;减慢代码执行速度;
动态链接库的创建
1>>打开Visual Studio选择创建新项选择动态链接库(DLL),点击下一步
2>>配置项目名称点击创建
3>>分别创建用于声明和定义函数的头文件.h和源文件.cpp
4>>定义和实现我们的函数
#pragma once
#include<iostream>
#ifdef Test_API
#define Test_API __declspec(dllexport)
#else
#define Test_API __declspec(dllimport)
#endif
// 导出函数
Test_API int Add(int a, int b);
// 导出类
class Test_API Test
{
public:
int Mul(int a, int b);
};
#include "pch.h"
#include "Test.h"
int Add(int a, int b)
{
return a + b;
}
int Test::Mul(int a, int b)
{
return a * b;
}
5>>生成解决方案
动态链接库的调用
加载方式:隐式加载和显式加载
隐式加载
所需文件:头文件、dll文件、lib文件
- 首先创建一个用于测试的空项目
- 隐式链接采用静态加载的方式,需要将创建的.dll文件以及.lib文件还有定义的.h头文件,拷贝至我们需要测试的新项目的目录下。
- 将拷贝的头文件添加到空白项目中
- 在属性—链接器—输入—附加依赖项中添加我们拷贝过来的.lib文件
- 创建一个.cpp源文件开始进行我们动态库的调用,包含头文件后直接可以调用我们封装的函数
#include <iostream>
#include "Test.h"
int main()
{
std::cout << "Hello World!\n";
std::cout << Add(1,2);
}
- 查看调用后的结果
显式加载
所需文件:dll文件。利用LoadLibrary()进行加载
LoadLibrary
该函数可用来动态加载dll文件,将指定的dll文件加载到当前进程的地址空间中,并返回一个模块句柄
#include <iostream>
#include "Test.h"
int main()
{
HINSTANCE ins = LoadLibrary(Test.dll);
std::cout << Add(1,2);
}
释放dll的函数为:FreeLibrary
GetProcAddress(Hinstance,lpname)
用来获取指定的动态链接库函数的地址。
Hinstance:由LoadLibrary返回的句柄
lpname:文件名/函数名
返回值:动态链接库的地址