再谈静态库和动态库(C++)
库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(.a、.lib)和动态库(.so、.dll)。1
在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中,所以称之为静态库,对应的链接方式称为静态链接。
静态库的特点有:
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。
动态库的特点有:
二者最大的不同点在于代码被载入的时刻不同
动态库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。带来好处的同时,也会有问题!如经典的DLL Hell问题,关于如何规避动态库管理问题,可以自行查找相关资料。
第一步:创建 Win32工程 MY_ADD,其中工程类型选择静态库(默认是控制台应用程序*)
第二步:在头文件新建 add.h ,代码如下:
//在这里写自己的代码,以下是例子
//注意:静态库中,申明和实现尽量分离,不要写到一块,易于后期维护
class Add{
public: //申明公有方法
int add2num(int a , int b); //只申明,不实现
};
第三步:在源文件下新建 add.cpp ,代码如下:
#include "add.h" //注意包含头文件
#include
int add::add2num(int a, int b){ //方法的实现
std::cout << "Successful" << std::endl;
return a + b;
}
第四步:编译该文件(注意:静态库文件不写 main 函数,所以只能编译),此时会在工程 Debug 目录下生成 MY_ADD.lib
第五步:在解决方案右键新建项目 TEST_LIB ,类型选择控制台应用程序(注意是在解决方案新建)
第六步:在 TEST_LIB 右键属性,通用属性 - 引用,选择刚才生成的 MY_ADD.lib,确定
第七步:在源文件新建 main.cpp ,代码如下:
#include "..//my_add/add.h" // ..// 代表当前目录,一定要添加该头文件
#include
#include
using namespace std;
int main(){
Add a;
int b = a.add2num(1,3);
cout << "This is abc program!\n";
printf("b = %d\n", b);
return 0;
}
第八步:将 TEST_LIB 设置为启动项,运行即可
第一步:把 add.h 和 MY_ADD.lib 复制我要调用的 TEST_LIB 目录下
第二步:添加如下头文件
#pragma comment(lib,"MY_ADD.lib")
#include "add.h"
当你新建一个项目,需要调用生成的 my_add.lib 时,也可以采用这种方法
第一步:建立自己的库目录文件夹,文件夹目录树如下:
第二步:打开VS,新建一个 Win32 工程,打开属性管理器(找不到可在 视图 - 其他窗口 - 属性管理器 找到),在 Debug | Win 32 右键添加新项目属性表,假设命名为 mylib.props
第三步:右键 mylib.props 属性,设置下面三项:
第四步:源文件下新建 main.cpp,输入:
#include //添加头文件
#include
using namespace std;
int main(){
Add a; //实例化
int b = a.add2num(1,2 ); //调用方法
cout << b << endl;
return 0;
}
第五步:编译并运行,完毕
强烈推荐该方法,因为这样方便以后添加自己的方法,调用方便,并且有效的保护了源代码
第一步: Win32 控制台程序,工程名称为 MYDLL,类型选择 DLL
第二步:头文件 - 新建 mydll.h,代码如下:
#pragma once
void p();
第三步:源文件 - 新建 mydll.cpp,代码如下:
#include "mydll.h"
#include
void p(){
std::cout << "DLL is successful" << std::endl;
}
第四步:源文件 - 新建 main.cpp,代码如下:
//定义 DLL 应用程序的入口点
#include //一定要包含这个头文件!!!
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
第五步:源文件 - 新建 Visual C++ - 代码 - 模块定义文件 - Source.def,代码如下:
LIBRARY "MYDLL"
EXPORTS
p @1
//如果还有别的函数要编译至dll文件,则按照这个规则继续写
//p1 @2
//p2 @3
//以此类推
第六步:生成解决方案,在工程目录下生成下面二个文件及其他文件:
你可以选择把 mydll.h、MYDLL.dll、MYDLL.lib拷贝至一个独立文件夹,之后进行引用就行
第一步:打开VS,新建一个工程,如:TEST_DLL,然后配置环境变量,具体操作为打开属性管理器,新建 mydll.props,然后右键 mydll.props 属性,分别配置:
第二步:打开VS,新建 main.cpp,代码如下:
#include
#include "mydll.h" //记得包含头文件
using namespace std;
int main(){
p(); //应用函数
return 0;
}
然后运行程序即可~~~
C++静态库与动态库 ↩︎
详解生成静态链接库lib文件和调用1 ↩︎
详解生成静态链接库lib文件和调用2 ↩︎