Linux 动、静态库的实现
前言:当我们写了一段代码实现了一个方法,如果我们不想把方法的实现过程暴露给别人看,可以把代码打包成一个库,其中形成后缀为.a的是静态库,后缀为.so的为动态库;当别人想使用你的方法时,把打包好的库跟头文件一起扔给他就行。
一、静态库
1.1生成一个简单的静态库
①首先创建两个文件,一个.c方法的实现,一个.h方法的声明;

②简单实现一下
//mymath.h文件
#pragma once int add(int x,int y);int sub(int x,int y);
//mymath.c文件1 #include "mymath.h" 2 int add(int x,int y) 3 { 4 return x+y; 5 } 6 int sub(int x,int y) 7 { 8 return x-y; 9 }
③makefile怎么写?
首先要把所有.c文件生成.o文件,然后把.o文件打包生成库(如果是静态库就是.a;如果是动态库就是.o)
//makefile文件1 lib=libmymath.a 2 $(lib):mymath.o 3 ar -rc $@ $^ ## ar :生成静态库命令; rc:把所有.o文件打包生成.a文件,如果.a里面已存在则覆盖; $@ :依赖目标 $^:依赖文件;4 mymath.o:mymath.c5 gcc -c mymath.c ##-c 默认生成.o文件6 .PHONY:clean ##清理7 clean:8 rm -rf *.o *.a mylib 10 .PHONY:output ##库发布 11 output: 12 mkdir -p mylib/lib #创建一串路径 13 mkdir -p mylib/include 14 cp *.h mylib/include #把头文件拷贝到include15 cp *.a mylib/lib #把.a 库文件拷贝到lib
~
④make一下
当前目录下已写好.c .h和makefile文件:

make后可以看到生成了mymath的.o文件,然后由.o文件生成静态库 libmymath.a:

⑤发布一下

查看一下当前目录:

可以看到生成的mylib文件就是我们制作的库文件,查看里面的内容:

可以看到其中include文件中包含了方法的头文件,lib文件中包含的就是静态库文件!
既然生成好了就来使用以下吧!
1.2 静态库的使用
①创建一个test文件然后把mylib文件拿过来用

②创建一个.c文件里面包含main函数来使用这个库

//main.c文件
1 #include "mymath.h"
2 int main()
3 {
4 printf("1+1= %d\n",add(1,1));
5 return 0;
6 }~
③静态库的编译链接

注意:库的编译链接:gcc + 带main函数的.c文件 + -I + 头文件所在的目录 + -L + 库所在的目录 + -l跟库真实的名字(去掉前缀去掉后缀)
编译后查看当前目录:

运行:

这样就成功的完成了静态库的制作到使用!接下来我们来实现下动态库吧!
二、动态库
2.1 生成一个简单的动态库
我们回到lesson16,然后makeclean,然后再创建两个.c文件分别存放两个方法,和其对应的.h方法使用声明(这两个方法用来生成动态库)

随便实现一下这两个方法(主要为了展示动态库的生成和使用):
//mylog.h文件1 #pragma once 2 void log(char* message);
//mylog.c文件1 #include "mylog.h"2 void log(char* message)3 {4 printf("%s\n",message); 5 }
//myprint.h文件1 #pragma once 2 void print();
//myprint.c文件1 #include "myprint.h"2 void print()3 {4 printf("hello linux!!!\n"); 5 }
2.2 makefile怎么写
首先makefile 一次生成两个库,一个静态库、一个动态库,生成之后发布为mylib(动、静态库、头文件都在里面):
//makefile文件1 static_lib=libmymath.a ##静态库2 dynamic_lib=libmymethod.so ##静态库3 .PHONY:all4 all:$(static_lib) $(dynamic_lib)5 $(static_lib):mymath.o6 ar -rc $@ $^ ## ar :生成静态库命令; rc:把所有.o文件打包生成.a文件,如果.a里面已存在则覆盖; $@ :依赖目标 $^:依赖文件;7 mymath.o:mymath.c8 gcc -c mymath.c ##-c 默认生成.o文件9 10 $(dynamic_lib):myprint.o mylog.o11 gcc -shared -o $@ $^ ##shared: 生成动态库12 myprint.o:myprint.c13 gcc -fPIC -c $^ ##fpic :产生位置无关码14 mylog.o:mylog.c15 gcc -fPIC -c $^16 .PHONY:clean ##清理17 clean:18 rm -rf *.o *.a mylib *.so 19 .PHONY:output ##库发布20 output: 21 mkdir -p mylib/lib #创建一串路径22 mkdir -p mylib/include 23 cp *.h mylib/include #把头文件拷贝到include24 cp *.a mylib/lib #把.a 库文件拷贝到lib25 cp *.so mylib/lib
make一下:

mymath生成的静态库libmumatg.a ; mylog和myprint生成的libmymethod.so动态库;
发布一下:

拿到test文件夹里用一下:
2.3 动态库的使用
创建一个main函数调用它:

//main.c文件
1 #include "mylog.h"
2 #include "myprint.h"
3 #include "mymath.h"
4 #include <stdio.h>
5 int main()
6 {
7 printf("1-1=%d\n",sub(1,1));
8 log("hello linux!!!\n");
9 print();
10 print();
11 return 0;
12 }
编译链接:

运行:

报错因为加载的时候找不到动态库,解决方法:
①、把库拷贝到系统默认的路径下 /lib64/usr/lib64/
②、在系统文件下创建软连接 /lib64/usr/lib64/
③、LD-LIBRARY_PATH 导入环境变量
④、进入/etc/ld.so.conf.d创建.conf文件并把库路径加进去,然后重新加载 ldconfig
这里我随便用一个,导入环境变量的方法:
导入前:

导入后:

再运行:

动态库使用成功!!
三、动态库如何实现?
相关文章:
Linux 动、静态库的实现
前言:当我们写了一段代码实现了一个方法,如果我们不想把方法的实现过程暴露给别人看,可以把代码打包成一个库,其中形成后缀为.a的是静态库,后缀为.so的为动态库;当别人想使用你的方法时,把打包好…...
C++11特性补充
目录 lambda表达式 定义 捕捉的方式 可变模板参数 递归函数方式展开参数包 数组展开参数包 移动构造和移动赋值 包装器 绑定bind 智能指针 RAII auto_ptr unique_ptr shared_ptr 循环引用 weak_ptr 补充 总结 特殊类的设计 不能被拷贝的类 只能在堆上创建…...
PcVue助力立讯:精密制造的智能化管控实践!
PcVue助力立讯: 精密制造的智能化管控实践! 客户介绍 立讯精密(Luxshare ICT,股票代码:002475)成立于2004年5月24日,专注于为消费电子产品、汽车领域产品以及企业通讯产品提供从核心零部件、…...
jmeter中文乱码问题解决
修改jmeter.properties配置文件 进入JMeter安装目录的bin文件夹,找到jmeter.properties文件。搜索参数sampleresult.default.encodingUTF-8,取消注释(删除行首的#),并将其值改为UTF-8。保存文件并重启JMeter生效…...
最新扣子空间实操指南
一、首先要先获取到内部测试的邀请码, 我们先打开扣子空间官网:https://space.coze.cn/ 输入邀请码后进入该页面: 它这里支持文件上传,扩展里面有很多插件,页支持MCP各种插件. 探索模式有两种,一种是ai自…...
Java表达式2.0
1 .数据类型转换 自动类型转换的规则 自动类型转换遵循一定的规则,这些规则确保了转换的合理性和安全性。以下是自动类型转换的主要规则: 容量小的类型自动转换为容量大的类型 Java中,数据类型的容量从小到大依次为:byte → shor…...
JavaScript 一维数组转二维数组
题目描述: <script>const num [1,2,3,4]const out (function(num,m,n){if(num.length ! m*n){return []}const newarr []for(let i 0;i<m;i){newarr.push(num.slice(i*n,(i1)*n))}return newarr})(num,2,2)console.log(out)</script>不使用Stri…...
WIN10重启开机不用登录,直接进入桌面
我们个人机不需要登录。 步骤1 置,帐户,登录选项,密码。 输入当前密码后,直接下一步。 再次重启,就会发现不需要密码了。...
JavaScript学习教程,从入门到精通,DOM节点操作语法知识点及案例详解(21)
DOM节点操作语法知识点及案例详解 一、语法知识点 1. 获取节点 // 通过ID获取 const element document.getElementById(idName);// 通过类名获取(返回HTMLCollection) const elements document.getElementsByClassName(className);// 通过标签名获取…...
基于ESP32 - S3实现一个ping百度的C测试程序
环境准备 安装ESP-IDF开发环境,可参考官方文档。确保开发环境已正确配置,能对ESP32 - S3进行编译和烧录。 实现思路 连接WiFi:让ESP32 - S3连接到一个可用的WiFi网络。初始化Ping功能:利用ESP-IDF提供的Ping API初始化Ping功能…...
英语学习4.15
amateur amateur 🔤 读音:/ˈmətər/ 或 /ˈmətʃʊr/ ✅ 词性:名词 / 形容词 ✅ 中文释义: (名词)业余爱好者 👉 指不是以此为职业的人,通常出于兴趣而从事某项活动。 …...
开源项目FastAPI-MCP:一键API转换MCP服务
在当今AI开发的世界中,应用程序与AI模型之间的无缝集成至关重要。 模型上下文协议(Model Context Protocol, MCP)通过允许AI模型访问外部工具和数据源,弥合了这一差距。 FastAPI MCP是一个强大的工具,它可以通过最少的配置将您现有的FastAPI端点转换为MCP兼容的工具。 本…...
python课堂随记
11.15 连接符 namemcl print(我叫,name) print(我叫name)#连接符 age18 print(我叫name年龄str(age)) #连接符需要数据类型相同 11.17随记 除法运算神奇 8/5 #1.6 8//5 #1 -8/5 #-1.6 -8//5 #-2 ##次方表示—两个** 3的27次方 27的3次方 小结 程序的书写&…...
Agent安装-Beszel 轻量级服务器监控平台
docker-compose安装 beszel-agent 安装 docker-compose 配置文件 services:beszel-agent:image: henrygd/beszel-agent:latestcontainer_name: beszel-agentrestart: unless-stoppednetwork_mode: hostvolumes:- ./beszel_socket:/beszel_socket- /var/run/docker.sock:/var…...
算法—选择排序—js(场景:简单实现,不关心稳定性)
选择排序原理:(简单但低效) 每次从未排序部分选择最小元素,放到已排序部分的末尾。 特点: 时间复杂度:O(n) 空间复杂度:O(1) 不稳定排序 // 选择排序 function selectionSort(arr) {for (let …...
websocket和SSE学习记录
websocket学习记录 websocket使用场景 即时聊天在线文档协同编辑实施地图位置 从开发角度来学习websocket开发 即使通信项目 通过node建立简单的后端接口,利用fs, path, express app.get(*, (req, res) > {const assetsType req.url.split(/)[…...
【统计分析120】统计分析120题分享
1-30 判断题 数学模型 指的是通过抽象、简化现实世界的某些现象,利用数学语言来描述他们的结构和行为,做出一些必要的假设,运用适当的数学工具,得到一个数学结论 数学模型:指的是通过抽象、简化现实世界的某些现象&am…...
【计量地理学】实验四 主成分分析与莫兰指数
一、实验内容 (一) 某地区35个城市2004年的7项经济统计指标数据见(数据中的“题目1”sheet)。 (1)试用最短距离聚类法对35个城市综合实力进行系统聚类分析,并画出聚类谱系图: 在此次实验内容…...
手写call,bind,apply
foo.Mycall(obj,1,2,3) Function.prototype.Mycallfunction(target,...args){if(typeof this!function){throw new TypeError(this is not a function)}// 判断target是否是对象if(targetnull||targetundefined){targetwindow}if(typeof target!object){targetObject(target)}/…...
【读书笔记·VLSI电路设计方法解密】问题64:什么是芯片的功耗分析
低功耗设计是一种针对VLSI芯片功耗持续攀升问题的设计策略。随着工艺尺寸微缩,单颗芯片可集成更多元件,导致功耗相应增长。更严峻的是,现代芯片工作频率较二十年前大幅提升,而功耗与频率呈正比关系。因此,芯片功耗突破…...
Ubuntu18.04安装Qt5.12
本文介绍了在Ubuntu18.04环境下安装QT QT5.12相关安装包下载地址 https://download.qt.io/archive/qt/5.12/ Linux系统下Qt的离线安装包以.run结尾 (sudo apt-get install open-vm-tools open-vm-tools-desktop解决无法paste的问题) 安装 1.cd命令 终端进入对应的文件夹下面 2.…...
【SpringBoot】99、SpringBoot中整合RabbitMQ实现重试功能
最近在做一个项目,需要使用 MQ 实现重试功能,在这里给各位分享一下。 1、整合 RabbitMQ <!-- rabbitmq消息队列 --> <dependency><groupId>org.springframework.boot</groupId><...
max31865典型电路
PT100读取有很多种方案,常用的惠斯通电桥,和专用IC max31865 。 电阻温度检测器(RTD)是一种阻值随温度变化的电阻。铂是最常见、精度最高的测温金属丝材料。铂RTD称为PT-RTD,镍、铜和其它金属亦可用来制造RTD。RTD具有较宽的测温范围&#x…...
每日一道leetcode(补充版)
1004. 最大连续1的个数 III - 力扣(LeetCode) 题目 给定一个二进制数组 nums 和一个整数 k,假设最多可以翻转 k 个 0 ,则返回执行操作后 数组中连续 1 的最大个数 。 示例 1: 输入:nums [1,1,1,0,0,0,1…...
数据通信学习笔记之OSPF的区域
OSPFArea 用于标识一个 OSPF 的区域 区域是从逻辑上将设备划分为不同的组,每个组用区域号 (Area ID)来标识 OSPF 的区域 ID 是一个 32bit 的非负整数,按点分十进制的形式(与 IPV4 地址的格式一样)呈现,例如 Area0.0.0.1。 为了简便起见&#…...
5 提示词工程指南-计划与行动
5 提示词工程指南-计划与行动 计划与行动 Cline 有两种模式: Plan 描述目标和需求、提问与回答、讨论、抽象项目的各个方面、确定技术路线、确定计划 计划与确认相当于架构师,不编写代码Act 按计划编写代码 按照计划编码Plan 模式的本质是构建实际编码前的上下文,Act 的本…...
如何一键批量删除多个 Word 文档中的页眉和页脚
在工作中,许多 Word 文档的页眉页脚中包含公司名称、Logo、电话等信息,用于对外宣传。但有时我们需要批量删除这些页眉页脚信息,尤其当信息有误时,手动逐个删除会增加工作量,导致效率低下。本文将介绍一种便捷的方法&a…...
QCustomPlot中自定义图层
QCustomPlot 使用图层(QCPLayer)系统来组织绘图元素的绘制顺序和可见性。下面详细介绍如何自定义图层并将可绘制对象关联到特定图层。 1. 理解 QCustomPlot 的图层系统 QCustomPlot 的图层系统具有以下特点: 图层按顺序排列,后绘制的图层会覆盖前面的图…...
Dubbo QoS操作手册
QOS 操作手册 QoS概述 启动参数 参数说明默认值qos-enable是否启动Qostrueqos-port启动Qos绑定的端口22222qos-accept-foreign-ip是否运行远程访问falseqos-accept-foreign-whitelist支持的远端地址ip地址(段)无qos-anonymous-access-permission-lefe…...
-实用类-
1. API是什么 2.什么是枚举 !有点类似封装! 2.包装类 注意: 1.Boolean类构造方法参数为String类型时,若该字符串内容为true(不考虑大小写),则该Boolean对象表示true,否则表示false 2.当包装类构造方法参…...
