Linux静态库与动态库的相关概念以及编程

本文介绍了Linux系统中分模块编程的优势,包括功能责任划分、便于调试和简化主程序。接着讲解了静态库和动态库的概念、特点及区别,静态库在运行时体积大但速度快,而动态库体积小但运行稍慢。通过一个计算器程序实例,详细阐述了如何将函数封装为静态库和动态库,并展示了编译过程。对于动态库的运行问题,提出了修改环境变量的方法来解决找不到库的问题。
摘要由CSDN通过智能技术生成

一.分模块编程:
当我们在实现一个项目的时候,比如wifi小车,我们会碰到超声波模块,电机模块,wifi模块等模块的开发,这时候,我们可以让不同的小组成员来完成不同的模块,作为项目负责人只需要调用他们的模块函数即可。
所以分模块编程有以下优点:
a.功能责任划分
b.方便调试
c.主程序简洁

二.静态库与动态库
1.介绍
使用GNU的工具我们如何在Linux下创建自己的程序函数库?一个“程序函数库”简单的说就是一个文件包含了一些编译好的代码和数据,这些编译好的代码和数据可以在事后供其他的程序使用。程序函数库可以使整个程序更加模块化,更容易重新编译,而且更方便升级。

程序函数库可分为3种类型:静态函数库(static libraries)、共享函数库(shared libraries)、动态加载函数库(dynamically loaded libraries)
动态函数库同共享函数库是一个东西(在linux上叫共享对象库, 文件后缀是.so ,windows上叫动态加载函数库, 文件后缀是.dll)
2.区别
a) 静态库
静态函数库,是在程序执行前(编译)就加入到目标程序中去了 ;
优点: 运行快
发布程序无需提供静态库,因为已经在app中,移植方便
缺点:大
b) 动态库
动态函数库,是在程序执行时动态(临时)由目标程序去调用
缺点: 运行慢
优点: 小

三.库的制作
先来看一下整体的代码,这是一个计算器:

#include<stdio.h>

int add(int a,int b)
{
int c;
c=a+b;
return c;
}

int sub(int a,int b)
{
int c;
c=a-b;
return c;
}

int mul(int a,int b)
{
int c;
c=a*b;
return c;
}

float div(int a,int b)
{
float c;
c=(float)(a/b);
}

int main()
{
int x;
int y;
printf("input NO.1 data\n");
scanf("%d",&x);
printf("input NO.2 data\n");
scanf("%d",&y);
printf("add:%d+%d=%d\n",x,y,add(x,y));
printf("sub:%d-%d=%d\n",x,y,sub(x,y));
printf("mul:%dx%d=%d\n",x,y,mul(x,y));
printf("div:%d/%d=%f\n",x,y,div(x,y));
return 0;
}

来看一下运行结果:
在这里插入图片描述我们把函数调用和主函数分开来试试(把函数调用封装成库)
静态库:
主函数

#include<stdio.h>
#include"func.c"
int main()
{
int x;
int y;
printf("input NO.1 data\n");
scanf("%d",&x);
printf("input NO.2 data\n");
scanf("%d",&y);
printf("add:%d+%d=%d\n",x,y,add(x,y));
printf("sub:%d-%d=%d\n",x,y,sub(x,y));
printf("mul:%dx%d=%d\n",x,y,mul(x,y));
printf("div:%d/%d=%f\n",x,y,div(x,y));
return 0;
}
~       

函数:

int add(int a,int b)
{
int c;
c=a+b;
return c;
}

int sub(int a,int b)
{
int c;
c=a-b;
return c;
}

int mul(int a,int b)
{
int c;
c=a*b;
return c;
}

float div(int a,int b)
{
float c;
c=(float)(a/b);
}

头文件:

int add(int a,int b);
int sub(int a,int b);
int mul(int a,int b);
float div(int a,int b);

怎么把他们编译到一起呢
经过一系列操作我们会得到以下文件:
calculator.c 原程序
func.c 被调用的函数
func.h 头文件
mainStatic.c 主函数
我们要做的是把2.3.4给串联起来,首先主函数包含头文件
#include"func.h"
接下来是对func函数进行两步操作
a. gcc xxx.c -c 生成xxx.o文件
b. ar rcs libxxx.a xxx.o xxx.o文件生成xxx.a静态库文件
示例:

gcc func.c -c//生成func.o
ar rcs libfunc.a func.o //libfunc.a是生成的库,func.o是材料

接下来我们编译主函数,让主函数链库

gcc mainStatic.c -lfunc -L ./ -o main 
//-lxxx就是连接哪个库,比如-lcurses就是调用ncurse图形库,-L./就是在当前路径下寻找库,不然会去/usr/lib里面找

编译完后我们会得到mian这个可执行文件,然后我们试一下,程序执行起来和原程序一样
在这里插入图片描述
动态库的制作:
首先我们做出func.so这个库

gcc -shared -fpic func.c -o func.so

-shared 指定生成动态库
-fpic 标准,fPIC 选项作用于编译阶段,在生成目标文件时就得使用该选项,以生成位置无关的代码。

然后我们编译主函数:

 gcc mainDy.c -lfunc -L ./ -o mainDy
 //mainDy.c就是主函数, 同样-lxxx链接库,然后在当前路径下连接,最后一个-o改一下名字

结果:
在这里插入图片描述
这里需要注意,一般来说这么写会报错,找不到库,因为系统默认是去/user/lib/里面去找的,由于该版本ubantu会自动帮我们去找到这个动态库所以没报错,但是在树莓派运行的linux上就会有报错,所以我们有什么解决办法呢
一般我们有这两种方法:
1.用超级用户权限(sudo)把编译好的.so库cp到/user/lib下面去(不建议)
2.更改环境变量:可以指定该程序运行时候,在LD_LIBRARY_PATH 所指定的路径去找库文件
export LD_LIBRARY_PATH="/xxx/xxx"
争对第二种方法,其实我们可以写一个脚本,即更改环境变量后再运行main函数的脚本:

export LD_LIBRARY_PATH="/home/CLC/Project3"
./mainDy

我们再用chmod +x给脚本文件加一个可执行权限,结果如下:
在这里插入图片描述以上就是关于Linux静态库与动态库的相关概念以及编程,尚有不足之处,请各位大神指正。
salute CLC

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值