Linux 动、静态库的实现

news2025/5/12 21:01:39

前言:当我们写了一段代码实现了一个方法,如果我们不想把方法的实现过程暴露给别人看,可以把代码打包成一个库,其中形成后缀为.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.c
  5   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  #把头文件拷贝到include
 15   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:all
  4 all:$(static_lib) $(dynamic_lib)
  5 $(static_lib):mymath.o
  6   ar -rc $@ $^ ## ar :生成静态库命令;  rc:把所有.o文件打包生成.a文件,如果.a里面已存在则覆盖;  $@ :依赖目标 $^:依赖文件;
  7 mymath.o:mymath.c
  8   gcc -c mymath.c  ##-c 默认生成.o文件
  9 
 10 $(dynamic_lib):myprint.o mylog.o
 11   gcc -shared -o $@ $^   ##shared: 生成动态库
 12 myprint.o:myprint.c
 13   gcc -fPIC -c $^  ##fpic  :产生位置无关码
 14 mylog.o:mylog.c
 15   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  #把头文件拷贝到include
 24   cp *.a mylib/lib    #把.a 库文件拷贝到lib
 25   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

这里我随便用一个,导入环境变量的方法:

导入前:

导入后:

再运行:

动态库使用成功!!

三、动态库如何实现?

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++11特性补充

目录 lambda表达式 定义 捕捉的方式 可变模板参数 递归函数方式展开参数包 数组展开参数包 移动构造和移动赋值 包装器 绑定bind 智能指针 RAII auto_ptr unique_ptr shared_ptr 循环引用 weak_ptr 补充 总结 特殊类的设计 不能被拷贝的类 只能在堆上创建…

PcVue助力立讯:精密制造的智能化管控实践!

PcVue助力立讯&#xff1a; 精密制造的智能化管控实践&#xff01; 客户介绍 立讯精密&#xff08;Luxshare ICT&#xff0c;股票代码&#xff1a;002475&#xff09;成立于2004年5月24日&#xff0c;专注于为消费电子产品、汽车领域产品以及企业通讯产品提供从核心零部件、…

jmeter中文乱码问题解决

修改jmeter.properties配置文件‌ 进入JMeter安装目录的bin文件夹&#xff0c;找到jmeter.properties文件。搜索参数sampleresult.default.encodingUTF-8&#xff0c;取消注释&#xff08;删除行首的#&#xff09;&#xff0c;并将其值改为UTF-8。保存文件并‌重启JMeter‌生效…

最新扣子空间实操指南

一、首先要先获取到内部测试的邀请码&#xff0c; 我们先打开扣子空间官网&#xff1a;https://space.coze.cn/ 输入邀请码后进入该页面&#xff1a; 它这里支持文件上传&#xff0c;扩展里面有很多插件&#xff0c;页支持MCP各种插件. 探索模式有两种&#xff0c;一种是ai自…

JavaScript 一维数组转二维数组

题目描述&#xff1a; <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 置&#xff0c;帐户&#xff0c;登录选项&#xff0c;密码。 输入当前密码后&#xff0c;直接下一步。 再次重启&#xff0c;就会发现不需要密码了。

开源项目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(场景:简单实现,不关心稳定性)

选择排序原理&#xff1a;&#xff08;简单但低效&#xff09; 每次从未排序部分选择最小元素&#xff0c;放到已排序部分的末尾。 特点&#xff1a; 时间复杂度&#xff1a;O(n) 空间复杂度&#xff1a;O(1) 不稳定排序 // 选择排序 function selectionSort(arr) {for (let …

【统计分析120】统计分析120题分享

1-30 判断题 数学模型 指的是通过抽象、简化现实世界的某些现象&#xff0c;利用数学语言来描述他们的结构和行为&#xff0c;做出一些必要的假设&#xff0c;运用适当的数学工具&#xff0c;得到一个数学结论 数学模型&#xff1a;指的是通过抽象、简化现实世界的某些现象&am…

【计量地理学】实验四 主成分分析与莫兰指数

一、实验内容 &#xff08;一&#xff09; 某地区35个城市2004年的7项经济统计指标数据见&#xff08;数据中的“题目1”sheet&#xff09;。 &#xff08;1&#xff09;试用最短距离聚类法对35个城市综合实力进行系统聚类分析&#xff0c;并画出聚类谱系图: 在此次实验内容…

手写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芯片功耗持续攀升问题的设计策略。随着工艺尺寸微缩&#xff0c;单颗芯片可集成更多元件&#xff0c;导致功耗相应增长。更严峻的是&#xff0c;现代芯片工作频率较二十年前大幅提升&#xff0c;而功耗与频率呈正比关系。因此&#xff0c;芯片功耗突破…

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.…

max31865典型电路

PT100读取有很多种方案&#xff0c;常用的惠斯通电桥&#xff0c;和专用IC max31865 。 电阻温度检测器(RTD)是一种阻值随温度变化的电阻。铂是最常见、精度最高的测温金属丝材料。铂RTD称为PT-RTD&#xff0c;镍、铜和其它金属亦可用来制造RTD。RTD具有较宽的测温范围&#x…

数据通信学习笔记之OSPF的区域

OSPFArea 用于标识一个 OSPF 的区域 区域是从逻辑上将设备划分为不同的组&#xff0c;每个组用区域号 (Area ID)来标识 OSPF 的区域 ID 是一个 32bit 的非负整数&#xff0c;按点分十进制的形式(与 IPV4 地址的格式一样)呈现&#xff0c;例如 Area0.0.0.1。 为了简便起见&#…

5 提示词工程指南-计划与行动

5 提示词工程指南-计划与行动 计划与行动 Cline 有两种模式: Plan 描述目标和需求、提问与回答、讨论、抽象项目的各个方面、确定技术路线、确定计划 计划与确认相当于架构师,不编写代码Act 按计划编写代码 按照计划编码Plan 模式的本质是构建实际编码前的上下文,Act 的本…

如何一键批量删除多个 Word 文档中的页眉和页脚

在工作中&#xff0c;许多 Word 文档的页眉页脚中包含公司名称、Logo、电话等信息&#xff0c;用于对外宣传。但有时我们需要批量删除这些页眉页脚信息&#xff0c;尤其当信息有误时&#xff0c;手动逐个删除会增加工作量&#xff0c;导致效率低下。本文将介绍一种便捷的方法&a…

QCustomPlot中自定义图层

QCustomPlot 使用图层(QCPLayer)系统来组织绘图元素的绘制顺序和可见性。下面详细介绍如何自定义图层并将可绘制对象关联到特定图层。 1. 理解 QCustomPlot 的图层系统 QCustomPlot 的图层系统具有以下特点&#xff1a; 图层按顺序排列&#xff0c;后绘制的图层会覆盖前面的图…