Linux下静态库与动态库制作及分文件编程

Linux下静态库与动态库制作及分文件编程

文章目录

  • Linux下静态库与动态库制作及分文件编程
    • 1.分文件编程
      • 1.1优点
      • 1.2操作逻辑
      • 1.3示例
    • 2.Linux库的概念
    • 3.静态库的制作与使用
      • 3.1优缺点
      • 3.2命名规则
      • 3.3制作步骤
      • 3.4开始享用
    • 4.动态库的制作与使用
      • 4.1优缺点
      • 4.2动态库命名规则
      • 4.3制作步骤
      • 4.4开始享用

1.分文件编程

这部分玩过单片机的都有所了解,在.c文件很多的时候,需要分文件编程,也叫模块化编程。

1.1优点

● 分模块的编程思想;

● 便于功能责任划分;

● 方便后期的维护和调试;

● 主程序更加简洁。

1.2操作逻辑

一篇代码基本可以分为三个部分,头文件部分,功能区部分,主函数main部分。那么分文件编程就是将这三个模块分别生成单独的代码文件。

● 功能区.c :只写功能实现的代码部分,可以不写头文件

● 主函数.c :写主函数main()的部分 ,和自己生成的“头文件.h”,用双引号“”,不用<>。

● 头文件.h :代码需要的所有头文件首先要写进去,然后功能区定义的函数及变量要写入(只写函数定义的区域,末尾加分号)。作用在于连接功能区代码和主函数代码。

1.3示例

输入两个数,分别计算出加减乘除后的值。

源代码示例(没用使用分文件编程的方式)

image-20240826095245822

代码拆分:采用分文件编程,将头文件区,功能代码区,主函数区分别建立代码文件

demo.h —— 头文件

#ifndef __DEMO_H		//加入预编译,防止重复加入头文件,命令方式以大写的头文件为名
#define __DEMO_H	#include <stdio.h>int add(int x,int y);//加法
int sub(int x,int y);//减法
int mul(int x,int y);//乘法
float div(int x,int y);//除法#endif

demo.c —— 主函数

#include "demo.h"//自建头文件,用双引号“”,里面包含功能区函数的定义及参数
//连接主函数和功能区代码 
int main()
{int data1;int data2;int value;printf("input a num:\n");scanf("%d",&data1);printf("input a num:\n");scanf("%d",&data2);printf("=============\n");printf("%d+%d=%d\n",data1,data2,add(data1,data2));//加printf("%d-%d=%d\n",data1,data2,sub(data1,data2));//减printf("%dx%d=%d\n",data1,data2,mul(data1,data2));//乘printf("%d/%d=%f\n",data1,data2,(float)div(data1,data2));//除return 0;
}

demo1.c —— 功能代码区

#include "demo.h"	//一般都会加自己的头文件,因为有些宏定义都会放到这个.h里面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 div(int x,int y)//除法
{return (float)x/y;
}

编译

//1.最笨的
gcc demo.c main.c
//2.利用*通配符,编译所有以.c为结尾的文件
gcc *.c

2.Linux库的概念

一个“程序函数库”简单的说就是一个文件包含了一些编译好的代码和数据,这些编译好的代码和数据可以在事后供其他的程序使用。程序函数库可以使整个程序更加模块化,更容易重新编译,而且更方便升级。

程序函数库可分为3种类型:静态函数库(static libraries)、共享函数库(shared libraries)、动态加载函数库(dynamically loaded libraries): (静态库,动态库,共享库)

1、静态函数库,是在程序执行前就加入到目标程序中去了 ;

通俗点说明:你可以使用我的代码,但是你不能看我的代码;

编译时,会链接到我们生成的库文件,程序可以正常编译运行,但如果常规使用vi打开库文件,就是一页乱码。

就是把上面的.c文件封装起来融合到主文件了,只有一个.h文件供你调用。

2、动态函数库同共享函数库是一个东西(在linux上叫共享对象库, 文件后缀是.so ,windows上叫动态加载函数库, 文件后缀是*.dll)

假如只有一个文件,那么静态库就很方便,但是如果有一百个文件,都用到了这个库文件,都融合到文件里面就会使得文件占得空间巨大,而且如果这个库文件更新迭代后,所有文件都要重新编译一下,如果是使用的动态库或者说共享库的话,这一百个文件共用这一个库文件,那么会省下很大一部分空间,在更新升级迭代后只需更新这一个库文件即可。

Linux中命名系统中共享库的规则

image-20240826102401211

3.静态库的制作与使用

目前不是那么常用了,不如动态库的种种,但是还是要学一下

静态函数库:是在程序执行前(编译)就加入到目标程序中去了 ;一般将功能性代码生成库文件

3.1优缺点

优点:
● 静态库在编译的时候就被打包到应用程序中,所以其加载的速度快;
● 发布程序的时候无需提供静态库,因为已经在app中,移植方便;

缺点:
● 链接时完整的拷贝到可执行文件中,被多次使用就会有多份冗余拷贝;
● 更新,部署,发布麻烦;

3.2命名规则

静态库文件的命名方式:“libxxx.a”,库名前加“lib”,后缀用“.a”,“xxx”为静态库名

动态库以.so为后缀

3.3制作步骤

原材料:xxx.c或者.cpp文件

  1. 制作成.o文件(-c在前在后无所谓)
gcc  -c xxx.c
  1. 生成静态库文件
ar rcs libtest.a xxx.o	//单个
ar rcs libtest.a xxx.o xxx.o //多个

生成的静态库文件通过主函数的链接后,正常编译运行,但并不能打开库文件查看里面的内容,也是库文件制作的目的所在

image-20240826104258329

其中:

ar rcs为固定命令,lib为固定开头,.a为固定结尾,中间的名字自己起

ar 命令里的内容 :

image-20240826104415900

3.4开始享用

你只知道他的头文件里面的函数有什么,怎么用,但是不知道这个函数具体是怎么实现的

1,mv xxx.c ~ 将原先的功能文件和生成的.o文件移至工作目录,只留下.h头文件和主函数文件,还有生成的静态库文件。

2,gcc xxx.c -ltest -L./ 编译

  • -l (L小写):链接生成的静态库文件,libtest.a需要“砍头去尾” test;
  • -L: 告诉gcc编译器从-L指定的路径去找静态库(当前路径)。默认是从/usr/lib/usr/local/lib中去找
orangepi@orangepizero2:~/file$ ls
demo1.c  demo1.o  demo.c  demo.h  libtest.a
orangepi@orangepizero2:~/file$ mv demo1.c demo1.o ~  //把多余的文件移动到工作目录
orangepi@orangepizero2:~/file$ ls   //只剩下库文件,头文件,主函数文件
demo.c  demo.h  libtest.a
orangepi@orangepizero2:~/file$ gcc demo.c -ltest -L./ //编译要链接库和路径
orangepi@orangepizero2:~/file$ ls  //编译成功,生成可执行程序a.out
a.out  demo.c  demo.h  libtest.a
orangepi@orangepizero2:~/file$ ./a.out //运行成功

4.动态库的制作与使用

动态函数库:是在程序执行时动态(临时)由目标程序去调用

4.1优缺点

优点:

  • 链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序可以共用,节省内存;
  • 程序升级简单,因为app中没有库的源代码,升级之后只要库的名字不变,函数名与及参数不变,只是做了优化,就能加载成功;

缺点:

  • 加载速度比静态库慢;
  • 发布程序时需要提供依赖的动态库;

4.2动态库命名规则

**动态库的命名方式:**与静态库类似,“libxxx.so”, 库名前加“lib”,后缀用“.so”,“xxx”为动态库名

4.3制作步骤

原材料:xxx.c 文件

  1. 将源文件生成.o,需要加一个参数fpic
gcc a.c b.c -c -fpic(fPIC)
  1. 生成.so文件:
gcc -shared  xxx.o -o libtest.so
//一步到位的操作,不再生成.o文件,直接到.so
gcc -shared  -fpic xxx.c -o libtest.sogcc -shared  -fpic xxx.c -o libtest.soarm-linux-gnueabihf-gcc -shared  -fpic *.c -o libtest.so

● -shared:必须使用的关键字,指定生成动态库;

● -fpic:执行标准,作用于编译阶段,在生成目标文件时就得使用该选项;

image-20240826111507976

4.4开始享用

gcc xxx.c -ltest -L./ 编译后生成默认a.out可执行程序,也可以自行-o生成执行程序

里面这些符号的含义,在静态库已做介绍,不再赘述

image-20240826112248056

编译没问题,但是结果出了问题。动态库运行和静态库的运行方式有区别的,静态库直接生在在可执行的程序中,而动态库是在程序执行时动态(临时)由目标程序去调用,需要去找到执行的文件目录,所以上面的动态库执行出错。

动态库默认不会去当前目录下找,而是去环境变量中找。

解决方法:把生成的动态库文件libtest.so拷贝到/usr/lib/这个路径下即可

为了让系统能找到要加载的共享库,有三种方法 :1.把库拷贝到/usr/lib和/lib目录下 
2.在LD_LIBRARY_PATH环境变量中添加库所在路径,,export  LD_LIBRARY_PATH=$LD_LIBRARY_PATH:你的动态库目录
3.添加/etc/ld.so.conf.d/*.conf文件,执行ldconfig刷新
sudo cp libtest.so /usr/lib/

image-20240826112347654

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/439550.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Uniapp API

1.uni.showToast 显示消息提示框 unishowToast({ obj参数 }) 2.uni.showLoading 显示 loading 提示框, 需主动调用 uni.hideLoading 才能关闭提示框。 3.uni.showModal 显示模态弹窗&#xff0c;可以只有一个确定按钮&#xff0c;也可以同时有确定和取消按钮。类似于一个A…

VLAN:虚拟局域网

VLAN:虚拟局域网 交换机和路由器协同工作后&#xff0c;将原先的一个广播域&#xff0c;逻辑上&#xff0c;切分为多个广播域。 第一步:创建VLAN [SW1]dispaly vlan 查询vlan VID&#xff08;VLAN ID&#xff09;:用来区分和标定不同的vlan 由12位二进制构成 范围: 0-4…

算法笔记(十一)——优先级队列(堆)

文章目录 最后一块石头的重量数据流中的第 K 大元素前K个高频单词数据流的中位数 优先级队列是一种特殊的队列&#xff0c;元素按照优先级从高到低&#xff08;或从低到高&#xff09;排列&#xff0c;高优先级的元素先出队&#xff0c;可以用 堆来实现 堆是一种二叉树的结构&…

HTB:Preignition[WriteUP]

连接至HTB服务器并启动靶机 靶机IP&#xff1a;10.129.157.49 分配IP&#xff1a;10.10.16.12 1.Directory Brute-forcing is a technique used to check a lot of paths on a web server to find hidden pages. Which is another name for this? (i) Local File Inclusion, (…

如何安全地大规模部署 GenAI 应用程序

大型语言模型和其他形式的生成式人工智能(GenAI) 的广泛使用带来了许多组织可能没有意识到的安全风险。幸运的是&#xff0c;网络和安全提供商正在寻找方法来应对这些前所未有的威胁。 随着人工智能越来越深入地融入日常业务流程&#xff0c;它面临着泄露专有信息、提供错误答…

2.创建第一个MySQL存储过程(2/10)

引言 在现代数据库管理中&#xff0c;存储过程扮演着至关重要的角色。它们是一组为了执行特定任务而编写的SQL语句集合&#xff0c;这些语句被保存在数据库中&#xff0c;并且可以被多次调用执行。存储过程不仅可以提高数据库操作的效率&#xff0c;还能增强数据的安全性和一致…

Docker 启动 Neo4j:详细配置指南和浏览器访问

Docker 启动 Neo4j&#xff1a;详细配置指南和浏览器访问 文章目录 Docker 启动 Neo4j&#xff1a;详细配置指南和浏览器访问一 Neo4j compose 得 yml 配置二 配置描述三 浏览器访问 这篇文章详细介绍了如何使用 Docker Compose 启动 Neo4j 数据库&#xff0c;包括 docker-com…

八大排序--01冒泡排序

假设有一组数据 arr[]{2&#xff0c;0&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;7} 方法&#xff1a;开辟两个指针&#xff0c;指向如图&#xff0c;前后两两进行比较&#xff0c;大数据向后冒泡传递&#xff0c;小数据换到前面。 一次冒泡后&#xff0c;数组中最大…

C++ | Leetcode C++题解之第459题重复的子字符串

题目&#xff1a; 题解&#xff1a; class Solution { public:bool kmp(const string& query, const string& pattern) {int n query.size();int m pattern.size();vector<int> fail(m, -1);for (int i 1; i < m; i) {int j fail[i - 1];while (j ! -1 &…

java基础_异常总结详解

1 列举一些列举常见的运行时异常 运行时异常都是 RuntimeException 子类异常 NullPointerException - 空指针异常 ClassCastException - 类转换异常 IndexOutOfBoundsException - 下标越界异常 ArithmeticException - 计算异常 IllegalArgumentException - 非法参数异常 Numb…

Elasticsearch:使用 LLM 实现传统搜索自动化

作者&#xff1a;来自 Elastic Han Xiang Choong 这篇简短的文章是关于将结构化数据上传到 Elastic 索引&#xff0c;然后将纯英语查询转换为查询 DSL 语句&#xff0c;以使用特定过滤器和范围搜索特定条件。完整代码位于此 Github repo 中。 首先&#xff0c;运行以下命令安装…

小阿轩yx-案例:jenkins部署Maven和NodeJS项目

小阿轩yx-案例&#xff1a;jenkins部署Maven和NodeJS项目 前言 在 Java 项目开发中&#xff0c;项目的编译、测试、打包等是比较繁琐的&#xff0c;属于重复劳动的工作&#xff0c;浪费人力和时间成本。以往开发项目时&#xff0c;程序员往往需要花较多的精力在引用 jar 包搭…

STM32的串行外设接口SPI

一、SPI简介 1.SPI总线特点 &#xff08;1&#xff09;四条通信线 SPI需要SCK、MISO、MOSI、NSS四条通信线来完成数据传输 &#xff0c;每增加一个从机&#xff0c;多一条NSS通信线。 &#xff08;2&#xff09;多主多从 SPI总线允许有多个主机和多个从机。 &#xff08;3&…

Markdown实用语法汇总

说明&#xff1a; 本来只展示本人常用的、markdown特有优势的一些语法。表格输入markdown的弱项&#xff0c;不作介绍&#xff0c;借助软件创建即可。引用图片、音频、视频等&#xff0c;虽然很方便&#xff0c;但是内容集成度不高&#xff0c;需要上传发布的时候很不方便&…

Linux高级编程_29_信号

文章目录 进程间通讯 - 信号信号完整的信号周期信号的编号信号的产生发送信号1 kill 函数(他杀)作用&#xff1a;语法&#xff1a;示例&#xff1a; 2 raise函数(自杀)作用&#xff1a;示例&#xff1a; 3 abort函数(自杀)作用&#xff1a;语法&#xff1a;示例&#xff1a; 4 …

GB28181信令交互流程及Android端设备对接探讨

GB28181规范必要性 好多开发者在做比如执法记录仪、智能安全帽、智能监控等设备端视频回传技术方案选型的时候&#xff0c;不清楚到底是用RTSP、RTMP还是GB28181&#xff0c;对GB28181相对比较陌生&#xff0c;我们就GB28181规范的必要性&#xff0c;做个探讨&#xff1a; 实现…

Pikachu-File Inclusion- 本地文件包含

前端每次挑选篮球明星&#xff0c;都会通过get请求&#xff0c;传了文件名&#xff0c;把页面展示出来&#xff0c;由于文件名时前端传给后台;并且查看源码&#xff0c;没有对参数做限制&#xff1b; 尝试直接从前端修改filename 参数&#xff1b; filename../../../../../../…

C++ | Leetcode C++题解之第458题可怜的小猪

题目&#xff1a; 题解&#xff1a; class Solution { public:int poorPigs(int buckets, int minutesToDie, int minutesToTest) {if (buckets 1) {return 0;}vector<vector<int>> combinations(buckets 1,vector<int>(buckets 1));combinations[0][0] …

交换排序:冒泡排序、递归实现快速排序

目录 冒泡排序 1.冒泡排序的核心思想 2.冒泡排序的思路步骤 3.冒泡排序代码 4.代码分析 5.对冒泡排序的时间复杂度是O(N^2)进行解析 6.冒泡排序的特性总结 递归实现快速排序(二路划分版本) 1.快速排序基本思路 2.代码思路步骤 3.代码实现 4.代码分析 (1)递归终止条…

基于H3C环境的实验——OSPF

目录 实验设备和环境 实验设备 实验环境 实验记录 1、单区域 OSPF基本配置 步骤1:搭建实验环境并完成基本配置 步骤2:检查网络连通性和路由器路由表。 步骤3:配置OSPF 步骤4:检查路由器OSPF邻居状态及路由表 实验设备和环境 实验设备 三台路由器、两台PC、电源线、两…