为什么要用库?
发可执行程序、有函数声明的头文件给别人,但是库的内容别人访问不到,把自己写的代码偷偷藏起来,很棒。
库的分类
1、静态函数库:是在程序执行前就加入到目标程序中去了 ,文件后缀名为.a
2、动态函数库同共享函数库是一个东西,在linux上叫共享对象库, 文件后缀是.so ,比如树莓派的wiringPi库,库名称就是libwiringPi.so
静态库的特点
静态函数库,是在程序执行前(编译)就加入到目标程序中去了 ;
优点: 运行快,发布程序(编译之后的可执行文件)无需提供静态库,因为已经在app中,移植方便
缺点:占用空间大
静态库的制作
第一步:
gcc calcufuncs.c -c //生成的是calcufuncs.o
第二步:
b.ar rcs libcalcufunc.a calcufuncs.o //xxx.o文件生成xxx.a静态库文件, 且.o文件可以不止一个
注意,静态库名称的格式为libname.a,编译时取name即可
静态库的使用
gcc calculatorT.c -lcalcufunc -L ./ -o staticPro
-lcalcufunc -l是制定要用的静态库,库名砍头去尾
-L告诉gcc编译器从-L制定的路径去找静态库。默认是从/usr/lib /usr/local/lib去找
main
#include <stdio.h>
#include "ca.h"
int main()
{
int a;
int b;
printf("intput a\n");
scanf("%d",&a);
printf("intput b\n");
scanf("%d",&b);
printf("a+b = %d\n",add(a,b));
}
头文件:ca.h
int add(int x,int y);
lib
int add(int x , int y)
{
return x + y;
}
int sub(int x ,int y)
{
return x - y;
}
int mul(int x ,int y )
{
return x * y;
}
float chufa(int x ,int y)
{
return (float)x / y;
}
动态库的特点
动态函数库,是在程序执行时动态(临时)由目标程序去调用
优点:节省空间
缺点: 运行慢,发布程序时需要搭配动态库
动态库的制作
gcc -shared -fpic calcufuncs.c -o libcalc.so
-shared 指定生成动态库
-fpic 标准,fPIC 选项作用于编译阶段,在生成目标文件时就得使用该选项,以生成位置无关的代码。
动态库的使用
gcc calculatorT.c -lcalc -L ./ -o mainProDy
-lcalc表示引用的动态库为:libcalc.so
-L告诉gcc编译器从-L制定的路径去找(./表示当前目录)。默认是从/usr/lib /usr/local/lib去找
但是编译可以通过,但是执行程序的时候会报错,这是为什么呢?这就回归到动态库的本质,是在程序执行时动态(临时)由目标程序去调用,Linux动态库的默认搜索路径是/lib和/usr/lib,当程序执行时需要某动态库,并且该动态库还未加载到内存中,则系统会自动到这两个默认搜索路径中去查找相应的动态库文件,但是这里面没有我们编译的库,
error while loading shared libraries: libcalc.so: cannot open shared object file: No such file or directory
通过指令添加环境变量
export LD_LIBRARY_PATH="/home/pi/back/test"
然后就可以执行成功了,但是但是但是但是还是存在小问题,每次关闭终端就会失效,需要重新配置环境变量。针对这个问题,我们可以写一个简单脚本:
vi start.sh //脚本的后缀是.sh
chmod +x start.sh //给脚本加权限
./start.sh //执行脚本
脚本的内容():
export LD_LIBRARY_PATH="/home/pi/back/test"//配置环境变量
./a.out //执行程序