1库的概念
为什么需要库?
(1)不希望别人看到代码的具体实现 ,但是又要给别人使用。
(2)方便我以后修改这个功能代码,而使用这个功能代码的其他代码不需要重新编译 。
库(Library)是一种代码的二进制封装形式 ,在其他的源代码中, 可以直接调用库, 但是又看不到他的具体实现。
库的这种方法有利于模块化, 而且只要接口设计得合理, 改变库的实现
不影响库的使用 。
库分为动态库和静态库 。
原先:
sum.c /sum.h
-->给别人使用
库:
sum.c /sum.h
--> 封装成库 —> 给要用的人
2 动态库的使用步骤
2.1 制作动态库
(1)编辑源代码(库的代码)
如:
xxx.c
功能函数的实现
xxx.h
函数以及数据类型等声明 “接口文件”
NOTE:一般来说不能把main函数
封装到库中
//也可以将其编译成目标文件 .o
(2)生成动态库
(arm-linux-)gcc -shared -fpic -o libxxx.so xxx.c
把xxx.c
(还可以加其他的.c
文件)编译成动态库
生成的动态库的名字为libxxx.so
(xxx就是库的名字)
-shared
生成动态库(共享库)
-fpic
:与位置无关
-o
:output 指定生成的动态库的名字
动态库的名字一般来说是lib
开头 以.so
结尾的文件名
lib[0-9a-zA-Z_]+\.so
2.2 使用动态库
(1)把头文件和库拷贝给别人
main.c
<----- libxxx.so
<----- xxx.h
(arm-linux-)gcc main.c -I 头文件的搜索目录 -L 库的搜索目录 -l 库名 -o main
-I
接一个目录 指定头文件的搜索路径 可以接多个-I
-L
接一个目录 指定库的搜索路径 可以接多个-L
-l
指定一个需要用到的库的名字 (除去前面的lib
和后面的.so
)
如:
(arm-linux-)gcc main.c -I ./ -L ./ -lsum -o main
上面这个命令 会生成一个可执行文件main
并且这个可执行文件main
会使用libsum.so
的内容,但是在生成main的时候 并没有把动态库中的内容拷贝到main中去,只是标记了一下main这个可执行文件,在运行的时候 需要用到libsum.so
这个库。
(2)在运行的时候 需要先指定动态库的加载路径
linux有一个环境变量 :LD_LIBRARY_PATH
加载库的路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home
/home就是你的动态库文件所在的路径
NOTE: 如果要到开发板上去执行使用库的话 记得使用arm-linux-gcc
需要把可执行文件和动态库文件都要下载到开发板上
思考:
在使用动态库的时候 并没有把动态库中的内容拷贝到可执行文件中去
只是做了一个标记 这样 就导致我们在运行可执行文件时 需要把可执行文件和动态库都要下载到开发板上
并且还要配置动态库的搜索路径 LD_LIBRARY_PATH
有人就提出 能不能把库的内容直接拷贝到需要它的可执行文件中去呢?
3 静态库
在使用静态库时 会把静态库的内容直接拷贝到可执行文件中去
这样的话 在运行可执行文件时 就不要再把静态库拷贝到开发板上去了
3.1 制作静态库
(1)编辑库的源代码 (功能代码)
sum.c/sum.h
sub.c/sub.h
(2)把各个源文件编译成目标文件 .o文件
gcc -c sum.c -o sum.o
gcc -c sub.c -o sub.o
(3)用ar命令把所有的.o文件 生成一个静态库
(arm-linux-)ar -rc libxxx.a sum.o sub.o
把sum.o sub.o
(还可以加其他的.o文件)打包生成一个静态库
静态库的文件名以lib开头 以.a结尾
3.2 使用静态库
(4)把头文件和静态库拷贝给需要的人
main.c
<— libxxx.a
<— xxx.h
gcc main.c -I ./ -L ./ -lxxx -o main
编译完成后可执行文件main 就包含了静态库中的用到的功能代码了
(5)直接把可执行文件(下载) 运行即可
4 动态库和静态库的区别
动态库和静态库都是库,都是代码的二进制封装形式
区别:
对于动态库 对使用动态库的代码 在编译时 并没有把动态库的内容拷贝进去
仅做了一个标记 我这个可执行文件在运行的时候 需要用到某某动态库
对于静态库 对使用静态库的代码 在编译链接的时候 直接把静态库的内容拷贝到可执行文件中去了
这样的话:
在运行可执行程序的时候 对于动态库而言
需要把动态库同时下载到目标板上区 并且还要配置动态库的搜索路径
在运行可执行文件时 对于静态库来说
直接运行即可
但是动态库 VS 静态库有两个明显的优势
(1)运行时刻 动态库在内存中只会有一次拷贝
而静态库的话 则会有多个拷贝(看多少个程序在使用这个静态库)“冗余”
(2)当接口一致的 更新动态库 不需要重新编译依赖该动态库的其他工程
如果是静态库修改了则需要重新编译依赖该静态库的工程