1.什么是库(函数库)
我们将实现某些特定功能的函数封装起来,就形成了库。说白了,库里面就是我们写的函数代码。
2.为什么需要库(函数库)
在一个工程当中,我们常常需要去写一些功能相同或相似的代码。为了开发更加的高效,所以我们就需要使用别人写好的函数(库),供我们调用。将函数封装起来,不仅方便了别人使用,而且还不会对别人开放代码,从而保护了知识产权。
注意:库里面封装的函数是不包含主函数的。
3.库的分类
我们一般将库分为动态库和静态库:
3.1:动态库
格式:lib+库名.so 比如:libfunc.so libadd.so
特点:使用动态库编译的程序占用空间比较小,因为程序运行时是依靠我们系统的动态库(需要设置环境变量)如果我们的系统库中(linux系统中在/lib或者/userlib目录下都可)没有程序运行的相关库文件,我们程序就不可以执行。动态库可以供多个程序同时使用。
动态库执行原理:
制作过程:
1.gcc -shared -fPIC -o libfunc.so A.c B.c (假设我们要将A.c和B.c的原文件封装成 libfunc.so 的动态库,func为动态库的名称)
-shared:表示生成的是.so动态库文件
-fPIC: 表示代码和地址无关,不需要被不同模块重定位,生成PIC代码。为了达到动态链接的目的。
2.sudo cp libfunc.so /lib/ (将上一步生成的libfunc.so动态库文件拷贝到系统的默认库文件目录下)
3.gcc main.c -o main -I 头文件的相对路径 -L 生成的动态库路径 -l库名 (编译main.c 但在编译时需要借助我们的生成的动态库)
注意:-I 表示头文件的相对路径 如在当前目录下可以写为-I ./ 或者直接不写-I ./ ; -L表示生成的动态库路径,我们第一次编译程序时必须要有编译的环境才可以。可以写为 -L ./ -lfunc (表示库在当前目录下,名称为func。-l和func之间没有空格)
4.执行main ./main (这时我们就可以删除当前目录下的库文件和A.c B.c,以及头文件 程序依然可以独立运行)
注意:使用动态库的源文件并不是只有将动态库复制到系统库文件目录下才能运行,我们还可以:
sudo gedit /etc/bash.bashrc
找到文件末尾,换行写入:
export LD_LIBRARY_PATH=动态库的绝对路径
保存关闭
让配置文件重新生效:source /etc/bash.bashrc(此时terminal显示会变色,间接说明你的设置生效了)
3.2:静态库
格式: lib+库名.a 比如:libfunc.a libadd.a
特点:使用静态库编译的程序占用空间比较大,编译过后,就不再需要库的支持,可以独立运行。因为在编译的过程中,程序将所需要的库文件编译进了程序。
制作过程:
1.gcc a.c -o a.o -c (如果a.c源文件中引入了头文件我们必须要要在后面追加 -I 头文件的路径)
gcc b.c -o b.o -c (我们将a.c b.c的源文件制作成为静态库 这里的.o表示可重定向文件)
2.ar cr libfunc.a a.o b.o (我们将上一步做好的.o文件 一起打包成为静态库libfunc.a )
ar: 打包工具,可以用来创建、修改库,也可以从库中提取单个模块
-c: 一个选项:表示创建一个库。不管库存不存在,都创建
-r: 一个选项:表示将模块(*.o)插入库中,如果库中本身有,就更新
3.gcc main.c -o main -I 头文件的相对路径 -L 生成的静态库路径 -lfunc 这里的func表示生成的静态库名称
4.执行main ./main
4.总结:
1.动态库和静态库的创建方式不一样,但是过程大致相同
2.动态库创建:找到需要封装为库的源文件---->使用动态库创建命令来创建库文件---->将库文件复制到系统/lib/或/userlib/目录下:目的是程序执行时会加需要的库文件,而程序会自动的向这个默认地址去找需要的库,当然我们可以用配置环境变量的方式将动态库所在路径配置为环境变量(3.1第4点已经详细说明如何配置)---->编译程序(这是成功的关键,当头文件在当前目录时,我们可以不写,但是无论是动态库还是静态库在编译时我们必须指定库的路径 格式为:-L 路径 -l库名)。
3.静态库的创建:找到需要封装的静态库源文件---->将源文件使用命令生成可重定向文件.o ---->将重定向文件打包为静态库.a---->
编译程序
4.无论是静态库还是动态库,,我们需要提供给别人使用的话,必须提供 库 + 头文件 。
5.常见错误,编译时提示找不到头文件,检查头文件是否在当前路径,如果不在 加上-I 的选项。
编译时提示找不到函数,检查头文件是否写错了,确认是否加上了-L 库的路径 -l库的名称 (小写l后面没有空格,库名称为去掉前缀和后缀后的名称,比如libfunc.so--->func libfunc.a--->func)
个人理解,如若不对请指正。