树莓派开发——Linux静态动态库
文章目录
一、分文件编程
1.1 分文件编程的优点:
- 分模块的编程思想:在实际工作中面对大型项目,可以让A完成串口开发;B完成网络开发,最后只需要他们提供h文件中的函数接口就可以在主函数中直接调用了,测试时发现哪部分有问题可以直接找负责的人,方便调试
- 代码可移植性更强:因为分文件编程了,串口,网络,语音可能都被封装好了,那么后续如果其他项目需要这些功能就可以直接调用封装好的接口了,最多只需要微调
- main函数更加精简:由于把功能性函数的实现步骤都封装到其他文件了,main函数就可以专注于项目的整体调用逻辑,使得整个main看起来更加清晰,逻辑通畅
1.2 分文件编程的步骤:
- 将功能性函数名和具体实现步骤写在一个**.c**文件中
- 创建一个同名的.h文件,包含所有可能会被调用的函数原型,去除函数体
- 在main中包含刚刚创建的**.h**文件
- 在main中调用被封装好的函数接口
- 使用gcc 编译所有相关的**.c文件**(封装函数的.c文件;main函数所在的.c文件)
- test.h文件的格式:
#ifndef __TEST_H__
#define __TEST_H__
int add(int x, int y);
int min(int x, int y);
float div(int x, int y);
#endif
- test.c文件的格式:
int add(int x, int y)
{
//函数体
}
int min(int x, int y)
{
//函数体
}
float div(int x, int y)
{
//函数体
}
- main函数调用h文件格式:
#include <stdio.h>
#include "test.h"
int main()
{
//函数体
return 0;
}
二、Linux的库
2.1 函数库的概念:
库(程序函数库)是一种可执行的二进制形式、就是将源代码转化为二进制格式,相当于进行了加密,别人可以使用库,但是看不到库中的内容。
库是别人写好的现有的,可以复用的代码,现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。
程序函数库可分为3种类型:静态函数库(static libraries)、共享函数库(shared libraries)、动态加载函数库(dynamically loaded libraries):
- 静态函数库:在程序执行前就加入到目标程序中的库, 文件后缀是.a
- 共享函数库:在程序执行时动态(临时)由目标程序去调用,共享函数库=动态函数库=共享对象库(Linux), 文件后缀是.so
- 动态加载函数库:本质上和共享函数库是一个东西,“动态加载数据库”是windows中的叫法,文件后缀是.dll
因此,对于Linux系统来说可以简单的将库分为 动态库 和 静态库
2.2 静态库和动态库的比较:
2.3 静态库的生成和使用:
2.3.1 静态库的制作步骤:
- 使用以下指令将**.c文件生成.o文件**
gcc a.c b.c -c
- 使用以下指令将**.o文件打包成.a库文件**
ar rcs 静态库的名字 原材料
例:ar rcs libXXX.a a.o b.o
这两步完成后,就生成了.a库文件,此时实现功能函数的.c文件和.o文件对于程序运行就不必要了,使得main函数可以调用这个库的条件就是有.h和.a文件,此时代码执行者可以调用库但却无法得知库中函数具体的实现步骤了。
2.3.2 静态库的使用:
gcc test_main.c -ltest_func -L ./ -o a.out //编译
gcc //使用gcc编译器编译
test_main.c //main函数
-ltest_func //-l(小写L):指定库的名字,库名砍头去尾
-L ./ //-L告诉gcc编译器从-L指定的路径(当前路径)去找静态库。默认是从/usr/lib /usr/local/lib去找
-o a.out //指定生成的最终应用程序的名字
2.4 动态库的生成和使用:
2.4.1 动态库的制作步骤:
- 使用以下指令生成动态库:
gcc -shared -fpic xxx.c -o libxxx.so
//-shared用来生成动态库
//-fpic选项作用于编译阶段,在生成目标文件时就得使用该选项,以生成位置无关的代码
2.4.2 动态库的使用:
gcc test_main.c -ltest_func -L ./ -o a.out //编译的语句其实和静态库相同
gcc //使用gcc编译器编译
test_main.c //main函数
-ltest_func //-l(小写L):指定库的名字,库名砍头去尾
-L ./ //-L告诉gcc编译器从-L指定的路径(当前路径)去找静态库。默认是从/usr/lib /usr/local/lib去找
-o a.out //指定生成的最终应用程序的名字
注意!虽然编译的语句相同,但是回顾动态库的缺点“需要提供依赖的动态库” ,所以编译完成后不能像使用静态库那样直接运行,这是因为动态库是程序运行中临时调用的,解决办法是将动态库拷贝到/usr/lib/下:
sudo cp libXXXX.so /usr/lib/
然后直接运行程序就可以了