1.静态库
1.1 什么是静态库?
我们先来说一下什么是静态库,维基百科对其的解释是这样的:
在计算机科学里,静态库(英语:Static library, Statically-linked library),或称静态库,是一个外部函数与变量的集合体。静态库的文件内容,通常包含一堆程序员自定的变量与函数,其内容不像动态链接库那么复杂,在编译期间由编译器与连接器将它集成至应用程序内,并制作成目标文件以及可以独立运作的可执行文件。而这个可执行文件与编译可执行文件的程序,都是一种程序的静态创建(static build)。以过去的观点来说,库只能算是静态(static)类型。
————维基百科
对于官方的解释总是令人头大,我们可以简单地认为静态库就是一组二进制代码(.obj)的集合,然后嵌入到我们的程序经过汇编形成的二进制文件中,最终形成可执行文件。
1.2 怎么创建静态库
1、我们先新建一个项目,选择win32项目
2、在接下来的应用程序向导中选择静态库并去掉预编译头的勾。
3、创建头文件(.h)以及源文件(.cpp),它们的格式如下:
//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;
}
4、然后,我们选择release,生成解决方案(这么简单的函数应该不用调试了吧)
5、随后,我们可以在自定的项目路径下的release文件夹下看到生成的lib文件。
1.3 如何使用静态库
关于静态库我们有两种使用方法,我们分别来介绍一下:
1.3.1 静态库的第一种使用方法
1、我们先创建个普通的win32控制台程序,选择空项目即可。
2、然后我们把上面创建lib时的头文件包含到新创建的控制台程序中:
3、然后在源程序中写如下格式的代码调用即可:
#include <iostream>
#include "MyLib.h"
#pragma comment(lib,"MyLib.lib")
int main()
{
STATIC_LIB::PrintHello();
system("pause");
return 0;
}
我们对#pragma comment中的内容做些说明,它搜索的路径就是在与项目文件名同名的文件夹下,所以我们可以直接将lib文件复制到该文件夹中,当然我们也可以使用绝对路径:
还需注意的是,刚才我们创建的lib是在release环境下创建出来的,此时调用也应在release环境下,不要出现鸡同鸭讲的情况,当然,你也可以都是在debug环境下环境下创建的。
1.3.2 静态库的第二种使用方法
1、我们创建一个include文件夹和lib文件夹用来存放头文件和lib文件:
2、项目名那右击,选择属性,在弹出的属性页窗口中选择VC++目录,然后添加进这两个文件夹
3、将先前创建lib时的头文件和lib文件分别复制到这两个文件夹中:
4、接着,再在属性页面中选择链接器--输入--附加依赖项中添加我们的lib
5、准备工作完成,在我们调用的程序中使用如下格式的代码即可调用:
#include <iostream>
#include "MyLib.h"
int main()
{
STATIC_LIB::PrintHello();
system("pause");
return 0;
}
成功运行的截图:
静态库的优点很明显,想想平时使用的标准库的优点就行了,但缺点当然也很明显,静态库是直接嵌入到可执行程序中的,会导致生成的可执行文件体积较大。当初正是为了避免此问题,才开发了动态库技术。
2. 动态链接库
2.1 什么是动态库?
以下是维基百科的解释:
动态链接库(英语:Dynamic-link library,缩写为DLL)是微软公司在微软视窗操作系统中实现共享函数库概念的一种实现方式。这些库函数的扩展名是
.DLL
、.OCX
(包含ActiveX控制的库)或者.DRV
(旧式的系统驱动程序)。所谓动态链接,就是把一些经常会共用的代码(静态链接的OBJ程序库)制作成DLL档,当可执行文件调用到DLL档内的函数时,Windows操作系统才会把DLL档加载存储器内,DLL档本身的结构就是可执行档,当程序有需求时函数才进行链接。透过动态链接方式,存储器浪费的情形将可大幅降低。静态链接库则是直接链接到可执行文件。DLL的文件格式与视窗EXE文件一样——也就是说,等同于32位视窗的可移植执行文件(PE)和16位视窗的New Executable(NE)。作为EXE格式,DLL可以包括源代码、数据和资源的多种组合。————维基百科
官方的解释就是这么高大上,粗人的理解就是相对于上面静态库,静态库是直接把代码嵌进去,而动态库则是类似独立的程序。打个比方的话就是静态库就是你留在这别走了,而动态库就是你要帮忙时叫我一下,我再来。
2.2 怎么创建动态库
动态库的创建和静态库类似
1、在win32向导中选择dll,并选择空项目创建。
2、建立如图几个文件
3、各个文件中的内容如下:
//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
这里对模块定义做一些说明(最后一个文件),LIBRARY后跟的是项目名,EXPORTS后是这个dll中需要导出的函数名。
2.3 如何使用动态库
动态链接库的使用方法也有两种
2.3.1 隐式调用
隐式调用就是把dll在程序运行前都先载入到内存中,然后程序运行后直接调用即可,实现方法如下:
1、创建win32控制台空项目
2、将上面创建Dll过程中的头文件(.h),lib文件以及dll文件复制到与项目同名的文件夹下:
3、然后写如下格式的代码即可调用
#include <iostream>
#include "MyDll.h"
#pragma comment(lib,"MyDll.lib")
int main()
{
DLL_TEST::PrintHello();
system("pause");
return 0;
}
我们说明一下,这里的lib文件是用来告诉程序dll中有哪些信息而已。
2.3.2 显式调用
显示调用借助了windows库
直接在调用程序中写如下代码即可调用:
#include <iostream>
#include <windows.h>
int main()
{
// TODO: Add your control notification handler code here
HINSTANCE hInst;
hInst = LoadLibrary(L"MyDll.dll");
typedef void(*Sub)();//函数指针
Sub PrintHello = (Sub)GetProcAddress(hInst, "PrintHello");//从dll中加载函数出来
PrintHello();//运行函数
FreeLibrary(hInst); //LoadLibrary后要记得FreeLibrary
system("pause");
return 0;
}
成功运行截图:
与隐形调用一股脑子地把所有dll加载到内存中不同,显式调用则是你要用到哪个dll就加载进来,不用了销毁了,极大地省下了空间,所以笔者推荐用第二种方法。
至此,静态库和动态库的创建和使用都介绍完毕了,也感谢各位看到此的读者,希望我的努力能让你进步一点点,这就够了!
参考资料: