静态链接库和动态链接库
静态库
- 静态库(.a、.lib)
- 编译分预编译,编译,汇编,链接,静态库是在链接阶段,将汇编代码中引用的静态库一起打包到可执行文件中
- 静态库也是一些.o文件的集合,所以才可以和汇编代码一起链接
- 编译阶就链接到一块,程序运行时,静态库不再参与
- 浪费空间,不同程序引用同一静态库,每个程序都需要链接到可执行文件里,拷贝一份
- 如果静态库修改,用户程序需要全量的重新编译
- 也就是静态库会在用户程序的源码里
静态库创建与使用
- .cpp -> .o -> .a /.lib
- linux下创建
1.编译
首先,将代码文件编译成目标文件.o(StaticMath.o)
g++ -c StaticMath.cpp
注意带参数-c,否则直接编译为可执行文件
2. 生成静态库.a文件
通过ar工具将目标文件打包成.a静态库文件
ar -crv libstaticmath.a StaticMath.o
生成静态库libstaticmath.a。
大项目会使用makefile或cmake来生成静态库
1.代码中引用
#include "StaticMath.h"
2.编译时再指定
g++ TestStaticLibrary.cpp -L 静态库路径 -l 静态库名称,省略后缀
//命令行
1.编译
首先,通过使用带编译器选项 /c 的 Cl.exe 编译代码 (cl /c StaticMath.cpp),创建名为“StaticMath.obj”的目标文件。
2.生成静态库.lib文件
然后,使用库管理器 Lib.exe 链接代码 (lib StaticMath.obj),创建静态库StaticMath.lib。
//用vs编辑器生成静态库
3.使用静态库
用vs编辑器使用静态库
动态库
- 动态库(.so、.dll)
- 解决静态库的空间浪费
- 动态库在用户程序运行时才链接、载入,不用在编译阶段链接(相当于复制)到户程序的源码里
- 进程之间的资源共享:不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例
- 动态库更新了,用户程序也不用重新编译
不同环境动态库编写的不同
在Windows系统下的执行文件格式是PE格式,动态库需要一个DllMain函数做出初始化的入口,通常在导出函数的声明时需要有_declspec(dllexport)关键字。
l Linux下gcc编译的执行文件默认是ELF格式,不需要初始化入口,亦不需要函数做特别的声明,编写比较方便
动态库创建与使用
- .cpp -> .o -> .so
- Linux下创建与使用
- .so后缀
- 用户程序实际装载动态库时,装在的是他的镜像,名字也是镜像的名字
- 用户程序如何找到动态库,如果用户程序是elf格式可执行文件,里面有个LD_LIBRARY_PATH环境变量,写了路径,从这个路径里面找到库文件。如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中
1.生成目标文件 .o
-fPIC 创建与地址无关的编译程序(pic,position independent code),是为了能够在多个应用程序间共享。
2.然后,生成动态库.so文件,此时要加链接器选项-shared
g++ -shared -o libdynmath.so DynamicMath.o
-shared指定生成动态链接库
3.其实上面两个步骤可以合并为一个命令:
g++ -fPIC -shared -o libdynmath.so DynamicMath.cpp
4.使用
代码中引用
#include "../DynamicLibrary/DynamicMath.h"
然后编译时再加命令
g++ TestDynamicLibrary.cpp -L.动态库路径 动态库名称,不要后缀
- windows 下
- 动态库的.lib文件只是实际动态库的一个导入库,表示了动态库的地址,很小的文件
- .dll
- 要更麻烦一些
1.先写一个DllMain函数的入口文件,dllmain.cpp
#include "stdafx.h"
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;
}
2.静态库文件的头文件里面,要有_declspec(dllexport)关键字
3.用vs编辑器生成静态库文件.o
4.使用静态库文件,在用户程序里引用静态库
5.用vs编辑器编译运行用户程序
动态库的显示调用
- 上面介绍的动态库使用方法和静态库类似属于隐式调用,编译的时候指定相应的库和查找路径。其实,动态库还可以显式调用。【在C语言中】,显示调用一个动态库轻而易举
- 有相应的函数
- c++调用麻烦些