一、命名规范
1.静态库
静态库的命名一般分为三个部分:
- 前缀:lib
- 库名称:自己定义即可
- 后缀:.a
所以最终的静态库的名字应该为:libxxx.a
2.动态库
共享库的命名一般分为三个部分:
- 前缀:lib
- 库名称:自己定义即可
- 后缀:.so
所以最终的动态库的名字应该为:libxxx.so
二、区别
静态库:一些目标代码的集合,是在可执行程序运行前就已经加入到执行码中,成为执行程序的一部分,如果有100个调用静态库的程序,静态库的代码就会调用100份,就会浪费空间,而动态库是不复制代码的,所以不浪费空间。
动态库:在程序编译时并不会被连接到目标代码中,而是在程序运行时才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该动态库的实例,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。
三、制作
静态库:
步骤1:将c源文件生成对应的.o文件
gcc -c add.c -o add.o
步骤2:使用打包工具ar将准备好的.o文件打包为.a文件 libtest.a
ar -rcs libtest.a add.o sub.o mul.o div.o
在使用ar工具是时候需要添加参数:rcs
r更新
c创建
s建立索引
动态库:
步骤一:生成目标文件,此时要加编译选项:-fPIC(fpic)
gcc -fPIC -c add.c
参数:-fPIC 创建与地址无关的编译程序(pic,position independent code),是为了能够在多个应用程序间共享。
步骤二:生成共享库,此时要加链接器选项: -shared(指定生成动态链接库)
gcc -shared add.o -o libtest.so
步骤三: 通过nm命令查看对应的函数
nm libtest.so | grep add 00000000000006b0 T add
四、使用
静态库:
静态库制作完成之后,需要将.a文件和头文件一起发布给用户。
假设测试文件为main.c,静态库文件为libtest.a头文件为head.h
编译命令:
deng@itcast:~/test/4static_test$ gcc test.c -L./ -I./ -ltest -o test
参数说明:
-L:表示要连接的库所在目录
-I./: I(大写i) 表示指定头文件的目录为当前目录
-l(小写L):指定链接时需要的库,去掉前缀和后缀
动态库:
第一步:引用动态库编译成可执行文件(跟静态库方式一样)
gcc test.c -L. -I. -ltest
当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统动态载入器(dynamic linker/loader)。
第二步:
(方法1:拷贝到标准库法)
将库文件复制到/lib/, /usr/lib目录,找到库文件后将其载入内存。
gcc test.c -I. -ltest
方法2:临时设置LD_LIBRARY_PATH:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径
方法3:永久设置,把export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径,设置到~/.bashrc或者 /etc/profile文件中
方法4:将其添加到 /etc/ld.so.conf文件中
编辑/etc/ld.so.conf文件,加入库文件所在目录的路径
sudo vim /etc/ld.so.conf
文件最后添加动态库路径(绝对路径)
运行sudo ldconfig -v,该命令会重建/etc/ld.so.cache文件(使生效)
方法5:使用符号链接, 但是一定要使用绝对路径
sudo ln -s /home/deng/test/6share_test/libtest.so /lib/libtest.so
Q:符号链接是什么?
A:符号链接是一类特殊的文件, 其包含有一条以绝对路径或者相对路径的形式指向其它文件或者目录的引用。(软链接)
示例:
MFCDLLTEST.h
class CMFCDLLTESTApp : public CWinApp
{
public:
CMFCDLLTESTApp();
// 重写
public:
virtual BOOL InitInstance();
DECLARE_MESSAGE_MAP()
};
extern _declspec(dllexport) int a;
extern "C" _declspec(dllexport) int b(void);
MFCDLLTEST.cpp
// MFCDLLTEST.cpp: 定义 DLL 的初始化例程。
//
#include "pch.h"
#include "framework.h"
#include "MFCDLLTEST.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
BEGIN_MESSAGE_MAP(CMFCDLLTESTApp, CWinApp)
END_MESSAGE_MAP()
// CMFCDLLTESTApp 构造
CMFCDLLTESTApp::CMFCDLLTESTApp()
{
// TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}
// 唯一的 CMFCDLLTESTApp 对象
CMFCDLLTESTApp theApp;
// CMFCDLLTESTApp 初始化
BOOL CMFCDLLTESTApp::InitInstance()
{
CWinApp::InitInstance();
return TRUE;
}
extern _declspec(dllexport) int a = 100;
extern "C" _declspec(dllexport) int b(void) {
printf("sdfasdase");
return 44;
}