能帮到你的话,就给个赞吧 ?
我们写程序的时候会需要加载库,一般需要先include头文件,然后再调用库函数,
而库又分为两种,静态库(lib)和动态库(dll),
那么这两种库有什么区别吗
静态库是我们的程序在链接时会把用到的静态库全部都链接进去,形成一个exe,这也导致我们的exe很大(程序是先编译,再链接库,最后形成exe)
而动态库则是在不再把整个库都链接进去,而是程序用到哪个库,再加载哪个库,这就降低了exe的大小,但同时,运行速度也会变慢。
当然,用动态库的话你的系统也需要有这些动态库,因为程序是没有的,所以啊,其实exe还是那么大,但是我们把exe的东西拿出来了,才降低了exe的大小。
这便是动态库和静态库的区别了。
在vs中创建和使用静态库和动态库
首先我们先建一个空程序(这个程序就用来使用我们的静态库和动态库)
文件->新建->项目 ->选择Visual C++ win32控制台应用程序 (名字就叫Use吧 ) ->下一步->然后选择控制台应用程序,再勾上空项目吧 -> 完成
此时是什么都没有的
关闭项目的话点击文件->关闭解决方案就行了
然后我们先来生成自己的静态库
静态库:
文件->新建->项目 ->选择Visual C++ win32控制台应用程序 (名字就叫MyLib吧 ) ->下一步->然后选择静态库,再取消预编译头吧 -> 完成
此时也是什么都没有的
然后我们在头文件和源文件中分别添加一个头文件和源文件
分别点击头文件和源文件 ->添加 -> 新建项 ->选择Visual C++中的代码 再分别选择头文件和cpp文件(名字就都叫MyLib吧)
代码如下
//MyLib.h
#pragma once
#ifndef _STATIC_LIB_H_
#define _STATIC_LIB_H_
#include <iostream>
namespace STATIC_LIB
{
void PrintHello(); //测试函数
}
#endif
//MyLib.cpp
#include "MyLib.h"
void STATIC_LIB::PrintHello()
{
std::cout << "Hello world!" << std::endl;
}
我要解释下,这个头文件呢是我们库的头文件,也就是别人使用我们库的时候要包含的那个头文件,源文件呢是用来生成库的,所以,别人用我们库的话要把这个头文件和一会生成的库文件都给他。
然后运行,
会生成一个lib文件,在你的项目目录下,默认是在debug下
好了,现在我们有了自己的静态库了,
那么怎么使用呢
打开Use 添加一个源文件
代码如下
#include <iostream>
#include "MyLib.h" //包含头文件
#pragma comment(lib,"MyLib.lib") //链接库文件
int main()
{
STATIC_LIB::PrintHello(); //调用库函数
system("pause");
return 0;
}
这个程序就用到了我们的库,我们可以先运行下
是会报错的
这是为什么呢,因为vs找不到我们的头文件和库文件,就报错了,那vs又是怎么找的呢
很简单,一个是当前项目的目录下
只有一个main.cpp源文件,肯定不行的啊
那我们把头文件和lib文件添加进去就行了
然后运行
ok
另一个呢就是在指定的目录下,我们先把头文件和库文件再删了
然后呢右键项目名称
属性 选择配置属性->VC++目录->找到包含目录和库目录 。包含目录是指定头文件的目录,库目录就是库目录啦,动态库也是这个,然后分别添加目录,目录就是我们刚才的头文件目录和库文件目录
就是这两个目录
然后确定
运行
ok
现在该动态库了
动态库:
文件->新建->项目 ->选择Visual C++ win32控制台应用程序 (名字就叫MyDll吧 ) ->下一步->然后选择Dll,空项目 -> 完成
此时是什么都没有的
然后添加如下三个文件
代码如下
//MyDll.h
#pragma once
#ifndef _DLL_TEST_H_
#define _DLL_TEST_H_
#include <iostream>
namespace DLL_TEST
{
void PrintHello();
}
#endif // !_DLL_TEST_H_
//MyDll.cpp
#include "MyDll.h"
void DLL_TEST::PrintHello()
{
std::cout << "Hello world!" << std::endl;
}
//MyDll.def
LIBRARY MyDll
EXPORTS
PrintHello
这里对最后一个文件解释下,def文件是库的说明文件,LIBRARY后跟的是项目名,EXPORTS后是这个dll中需要导出的函数名。
然后运行
会生成如下文件
其中我们需要知道的dll就是我们的动态库,而lib文件叫做导入库,和静态库不是一个东西,但后缀名一样,导入库的作用就是导入,用来导入动态库
然后对我们的Use进行更改
代码如下
#include <iostream>
#include "MyDll.h"
#pragma comment(lib,"MyDll.lib")
int main()
{
DLL_TEST::PrintHello();
system("pause");
return 0;
}
这个是不是和静态库差不多,哈哈~
我们还是先来运行下,是会报错的。
我们同样需要复制,这次要多一个dll,要把头文件和导入库文件和dll都复制过去(当然你也可以改目录)
然后运行
ok
上面这种叫隐式调用,如你所见,代码跟静态库差不多,但是有一点不同,加载的那个lib是导入库,并不是动态库,而导入库并无我们的库函数代码,我们动态库依旧是随用随到,导入库只起到导入的作用,也会全部链接进去,但是由于导入库很小,所以exe还可以很小。
下面介绍显示调用
先把上面那三个给删了
然后改main代码
代码如下
#include <iostream>
#include <windows.h>
int main()
{
// TODO: Add your control notification handler code here
HINSTANCE hInst;
hInst = LoadLibrary(L"MyDll.dll"); //加载dll库
typedef void(*Sub)();//函数指针
Sub PrintHello = (Sub)GetProcAddress(hInst, "PrintHello");//加载库函数
PrintHello();//运行函数
FreeLibrary(hInst); //释放库
system("pause");
return 0;
}
我们先来试下
运行
会中断,我们先把程序关了。
这是为什么呢,因为我们的程序会用到dll,但是现在项目目录下没有,我们又没指定,所有就中断了,我们再复制下dll
然后运行
ok
好啦,看下显式调用的代码,你就知道库是我们自己加载和释放的,所以这叫显示调用,上面那叫隐式调用,而显式调用也不需要链接导入库,甚至连头文件也不要,因为是我们自己指定加载的嘛,所以,懂了没~
参考资料:
手把手教你如何制作和使用lib和dll
Windows静态链接库与动态链接库的创建和显式与隐式调用
Visual Studio中VC++目录与C/C++及链接器的包含目录、库目录的区别
动态链接库的优缺点