Linux——动静态库的制作和使用超详细(实操+代码+原理介绍)

news2024/11/27 14:49:46

0

动静态库的制作和使用

  • 1️⃣.动静态库介绍
    • 🏀静态库
    • ⚽️动态库
    • 🏈区别
    • 🏐使用动态库的优点包括:
    • 🏉 使用静态库的优点包括:
  • 2️⃣静态库的制作
    • 🍊Q:库文件能不能有main()函数?
    • 🍋准备好库函数.h和.c文件
    • 🍉归档
    • 🍇静态库发布
  • 3️⃣ 动态库的制作
    • 🍒规则
    • 🍑实操代码
  • 4️⃣使用 静态库
    • 🍍 头文件搜索路径规则
      • 🚴🏼‍♀️ 库的安装
        • -I -L -l介绍
  • 5️⃣使用动态库
    • 🍓

1️⃣.动静态库介绍

🍏动态库(Dynamic Library)和静态库(Static Library)是在软件开发中常用的两种库文件形式。

🏀静态库

静态库是一组已编译的目标文件的集合,它们被打包成一个单独的文件。当程序链接时,编译器会将静态库的目标文件直接嵌入到最终的可执行文件中。静态库在编译时被完整地复制到可执行文件中,使得可执行文件成为一个独立、自包含的实体。这意味着程序运行时不需要额外的库文件支持,所有所需的代码都已嵌入到可执行文件中。静态库的扩展名通常是 .a(对于UNIX/Linux)或 .lib(对于Windows)。

⚽️动态库

相比之下,动态库是一组已编译的目标文件的集合,它们在运行时由操作系统动态加载到内存中。当程序链接时,编译器只会在可执行文件中包含动态库的引用,而不会将实际的代码嵌入到可执行文件中。程序在运行时,通过动态链接器(如 Windows 的 DLL 动态链接库或 UNIX/Linux 的共享对象文件 .so)将动态库加载到内存,并与可执行文件进行连接。动态库的扩展名通常是 .so(对于UNIX/Linux)或 .dll(对于Windows)。

🏈区别

  • 静态库的代码在编译时被复制到可执行文件中,使得可执行文件自包含,无需外部依赖。
  • 动态库的代码在运行时动态加载到内存中,多个程序可以共享同一个动态库,减少内存占用和可执行文件的大小。

🏐使用动态库的优点包括:

  1. 节省内存和磁盘空间,多个程序可以共享同一个动态库。
  2. 允许在运行时更新和升级库,而无需重新编译整个程序。
  3. 支持动态链接,使得程序更灵活、易于维护和分发。

🏉 使用静态库的优点包括:

  1. 代码的嵌入性,可执行文件自包含,无需外部依赖。
  2. 可以确保程序与特定版本的库文件完全兼容。
  3. 选择使用动态库还是静态库,通常取决于项目的需求、开发环境和目标平台等因素。在实际开发中,通常会根据实际情况进行权衡和选择。

2️⃣静态库的制作

🍊Q:库文件能不能有main()函数?

		A:不能 ,制作的库函数是给别人使用的,两个main函数会引起冲突! 

🍋准备好库函数.h和.c文件

这里我以static.c static.h static2.c static2.h 命名 写了2个打印函数
0

  • 🙋🏿‍♀️ static.c
 #include"static.h"
    void _Printf(int i)                                                                                                                                                                    
    {
      while(i>0)
      {
     printf("这是一个静态库\n");
      i--;
      }
    }

  • 🙋🏿static.h
 #pragma once 
    #include <stdio.h>
    void _Printf(int i); 
  • 🤦🏿‍♀️ static2.h
#pragma once 
    #include<stdio.h>
    void Print2(int x);
  • 🤦🏿static2.c
 #include "static2.h"
    void Print2(int x)
      {
        while(x>0)
      {
      printf("这是static2.....\n");                                                                                                                                                        
     x--;                                                                                                                                                                                    } 
     }

然后在test.c中包含头文件 static.h 这里跟我们平时在VS下写代码 声明和定义分离是一样的道理

  • 🙋🏿‍♂️test.c
  #include"static.h"
    int main()
    {
     _Printf(10) ;
     Print2(5);
     return 0;                                                                                                                                                                             
   }
    
~

  • 👋🏼形成.o文件
    gcc -c 源文件.c -o 生成件.o
    这里我们直接把配置生成代码写在makefile
 all: static.o static2.o
  static.o: static.c
      gcc -c static.c -o static.o
    static2.o: static2.c
     gcc -c static2.c -o static2.o
   .PHONY:clean                                                                                                                                                                           
    clean:
     rm -f *.o

3
生成了可执行对应的.o文件

用gcc 编译一下生成的.o文件
5
就得到了a.out

  • 🤚🏼运行
    6
  • 🖐🏼达到预期
  • 🤏🏼很多.o文件在一起用起来操作比较繁琐 有没有什么方式处理一下呢?

🍉归档

6

  • ✋🏼命名规则:
    生成的静态库名.a +依赖的.o文件
    ar - rc 生成的静态库名.a +依赖的.o文件

  • 🖖🏼编译结果:
    7
    生成了 libsatitic静态库!!!

🍇静态库发布

  • 👌🏼 makefile
    9
  • 形成
    10

3️⃣ 动态库的制作

🍒规则

  • 🤞🏼shared: 表示生成共享库格式
  • 🤘🏼fPIC:产生位置无关码(position independent code)
  • 🤙🏼库名规则:libxxx.so
  • 👈🏼示例: [root@localhost linux]# gcc -fPIC -c sub.c add.c [root@localhost linux]# gcc -shared -o libmymath.so
    *.o [root@localhost linux]# ls add.c add.h add.o libmymath.so main.c sub.c sub.h sub.o

🍑实操代码

动态+静态

.PHONY:all
   all:libstatic.so libstatic.a
    libstatic.so:static.o static2.o
      gcc -shared -o libstatic.so static.o static2.o
    static.o:static.c
      gcc -fPIC -c static.c -o static.o
   static2.o:static2.c
      gcc -fPIC -c static2.c -o static2.o 
  
  libstatic.a:static_s.o static2_s.o
    ar -rc libstatic.a static_s.o static2_s.o
  static_s.o:static.c
    gcc -c static.c -o static_s.o
  
  static2_s.o:static2.c
    gcc -c static2.c -o static2_s.o
  
  .PHONY:lib
  lib:  
    mkdir -p lib-static/lib;
      mkdir -p lib-static/include;
       cp *.a lib-static/lib;
      cp *.h lib-static/include;
       mkdir -p lib-dyl/lib 
       mkdir -p lib-dyl/include
      cp *.so lib-dyl/lib 
      cp *.h lib-dyl/include
   .PHONY:clean
   clean:
     rm -f *.o *.a *.so 
     rm -rf lib-static lib-dyl   

11

  • 代码讲解
  • 这个 Makefile 脚本是用来构建两个库文件:一个动态链接库 (libstatic.so) 和一个静态链接库 (libstatic.a),并将它们复制到对应的目录中。下面我会逐行解释这个脚本:

.PHONY: all:这行定义了一个伪目标 “all”。在 Makefile 中,伪目标并不对应任何文件,只是一个便于调用的标签。

all: libstatic.so libstatic.a:这行定义了目标 “all” 的依赖项。当你只输入 make (默认目标是 “all”)时,make 将会按照顺序构建 libstatic.so 和 libstatic.a。

3-4. libstatic.so: static.o static2.o 和 gcc -shared -o libstatic.so static.o static2.o:这两行定义了如何构建 libstatic.so。当 static.o 或 static2.o 发生变化时,make 将会重新生成 libstatic.so。

5-8. 这些行定义了如何生成 static.o 和 static2.o,都是从对应的 .c 文件编译得到。

10-11. libstatic.a: static_s.o static2_s.o 和 ar -rc libstatic.a static_s.o static2_s.o:这两行定义了如何构建 libstatic.a。

12-16. 这些行定义了如何生成 static_s.o 和 static2_s.o,都是从对应的 .c 文件编译得到。

.PHONY: lib:这行定义了另一个伪目标 “lib”。
20-28. 这些行定义了目标 “lib” 的行为,用于创建两个目录 lib-static 和 lib-dyl,并将构建好的库文件和头文件复制到对应的目录中。

.PHONY: clean:这行定义了另一个伪目标 “clean”。
30-32. 这些行定义了目标 “clean” 的行为,用于删除所有构建好的目标文件,以及 lib-static 和 lib-dyl 目录。这样可以方便地重建所有目标。

这个 Makefile 脚本使用了一些通用的 make 和 shell 命令,例如 gcc(C 编译器)、ar(用于创建、修改、提取静态库的工具)、mkdir(创建目录)、cp(复制文件)和 rm(删除文件)。在这个脚本中,它们被组合在一起,用于构建和管理 C 项目。

  • 运行:
    12

4️⃣使用 静态库

直接包头文件使用
13
报错了:
在这里插入图片描述
找不到!!

🍍 头文件搜索路径规则

  • 👶🏼 在当前路径下找
  • 👧🏼在系统头文件路径下查找头文件

🚴🏼‍♀️ 库的安装

  1. 将头文件和自己的库文件拷贝到系统路径下!
    不推荐! 会污染系统的头文件和库…
  2. 指定头文件搜索路径(推荐)

== 语法:-I +搜索路径 ==
gcc test.c -o test -I ./lib-static/include/
在这里插入图片描述

-I -L -l介绍

66
-I:头文件查找的路径
-L: 库文件搜索的路径
-l:在-L指定的路径下 选择你要链接的库(有时候-L路径会有多个库文件)

🚴🏼 🚴🏼‍♂️

🧒🏼 👦🏼 👩🏼 🧑🏼 👨🏼 👩🏼‍🦱

5️⃣使用动态库

6️⃣

🍓

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

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

相关文章

clickhouse基础数据类型 语法及使用可视化数据库工具 DBeaver

新建一个名为 test 的数据库&#xff1a;右击数据库点击新增&#xff0c;然后创建一张 test &#xff0c;utf8mb4 字符的&#xff0c;点击确定 在 test 数据库下新建一张数据表&#xff0c;如下所示&#xff1a;右击表&#xff0c;然后点击新建表 鼠标放列上面&#xff0c;右键…

b站视频播放三倍速

目录 一、操作 一、操作 document.querySelector(video).playbackRate 31、F12或者在当前界面鼠标右击选择检查 打开开发者工具平台 2、在console界面执行document.querySelector(video).playbackRate 3 document.querySelector(video).playbackRate 3

vector模拟实现

目录 vector相关接口实现 使用memcpy拷贝问题 迭代器失效 引起失效的操作 指定位置元素的删除操作 ​编辑引起底层空间改变的操作 vector相关接口实现 template<typename T> class vector { public:typedef T* iterator;typedef const T* const_iterator; public:…

基于MSP432P401R跟随小车(一)【2022年电赛】

文章目录 一、赛前准备1. 硬件清单2. 工程环境 二、赛题思考三、软件设计1. 路程、时间、速度计算2. 距离测量3. 双机通信4. 红外循迹 四、技术交流 一、赛前准备 1. 硬件清单 主控板&#xff1a; MSP432P401R测距模块&#xff1a; GY56数据显示&#xff1a; OLED电机&#x…

MinUv2靶场详解

MinUv2靶场详解 这个靶场我学到了.bash_history文件&#xff0c;每个用户都有一个名为 .bash_history 的文件&#xff0c;它位于用户的主目录中&#xff0c;默认有500行最近执行的命令。 这个靶场我用vmware是不能打开的&#xff0c;用virtualBox就可以&#xff0c;并且打开时…

MySQL索引、事务

目录 索引 作用 查看索引 创建索引 删除索引 索引背后的数据结构 B树 B树 事务 事务的本质 事务的特性 并发执行事务产生的问题 脏读问题 不可重复读 幻读 MySQL中隔离级别 read uncommitted readcommitted repeatable read serializable 索引 索引的本质…

SolidUI AI生成可视化,0.1.0版本模块划分以及源码讲解

1.背景 随着文本生成图像的语言模型兴起&#xff0c;SolidUI想帮人们快速构建可视化工具&#xff0c;可视化内容包括2D,3D,3D场景&#xff0c;从而快速构三维数据演示场景。SolidUI 是一个创新的项目&#xff0c;旨在将自然语言处理&#xff08;NLP&#xff09;与计算机图形学相…

【Java虚拟机学习1】JVM运行时数据区

JVM运行时数据区 一、前言 我们知道Java程序是运行在JVM&#xff08;Java虚拟机&#xff09;上的&#xff0c;Java程序运行时会占用一定的内存&#xff0c;在虚拟机自动管理机制的帮助下&#xff0c;不再需要为每一个new操作去写配对的delete/free代码&#xff0c;不容易出现…

指针进阶详解(下)

指针进阶详解&#xff08;下&#xff09; 前言1. 函数指针1.1 两端有趣代码 2. 函数指针数组2.1 函数指针数组的用途之一&#xff1a;转移表 3. 指向函数指针数组的指针4. 回调函数5. 结尾 前言 在指针进阶详解&#xff08;上&#xff09;中&#xff0c;我们已经介绍了部分指针…

基于数据安全的风险评估(三):风险分析与评估

完成了资产识别、脆弱性识别及威胁识别后&#xff0c;我们可以采用适当的方法和工具确定威胁利用脆弱性导致安全事件发生的可能性。综合安全事件作用资产价值及脆弱性的严重程度&#xff0c;判断事件造成的损失及对组织的影响&#xff0c;即安全风险。 一 风险计算形式及关键环…

HTTP协议对比HTTPS协议

HTTP协议对比HTTPS协议 1. HTTP协议1.1 概述1.2 HTTP协议格式1.3 HTTP协议支持的方法1.3.1 GET方法1.3.2 POST方法1.3.3 其他HTTP方法1.3.4 GET对比POST 1.4 请求报文1.4.1 Content-Type&#xff1a;请求体中数据格式1.4.2 Cookie&#xff1a;浏览器缓存 1.5 响应报文1.5.1 状态…

LED驱动(原始架构优化:分层/分离)——STM32MP157

文章目录 优化思想&#xff1a;分层Demo的LED驱动程序led_opr.hboard_demo.cleddrv.cledtest.cMakefile编译测试 STM32MP157的LED驱动程序board_stm32mp157.cleddrv.cled_opr.hMakefiel编译测试 优化思想&#xff1a;分离Demo的LED驱动程序led_resource.hboard_A_led.cchip_dem…

MacOS系统(M1/M2)安装AI绘画StableDiffusion保姆级教程

TOC 安装完成后&#xff0c;推荐阅读这篇教程&#xff1a;AI绘画&#xff1a;Stable Diffusion 终极炼丹宝典&#xff1a;从入门到精通 实操环境&#xff1a; macOS 13 Arm64&#xff08;建议12以上的系统使用&#xff09; Apple M1 先来看几个样例&#xff1a; AI绘画S…

goland自定义代码模版

在 GoLand 中我们既可以修改已有代码模版&#xff0c;也可以新建属于我们自己的代码模版&#xff0c;按需配置。 一、修改已有代码模版 现在代码编辑页输入你想更改的代码模版&#xff0c;然后点击右下角的小灯泡按钮&#xff0c;接着选中编辑活动模版设置即可。 二、新建…

[机缘参悟-99] :关于局部最优与全局最优解的人生感悟

在没有获取全局信息之前&#xff0c;要获得全局最优解几乎是不可能的&#xff0c;最多是概率大一点而已&#xff0c;大多数时候&#xff0c;由于时空资源的限制&#xff0c;获得往往是局部最优解&#xff0c;局部最优解&#xff0c;放在全局&#xff0c;往往并非全局最优&#…

数学专题训练3 数论1

1. Problem - 27E - Codeforces 给定 n ( 1 ≤ n ≤ 1000 ) n(1 \le n \le 1000) n(1≤n≤1000)​​​&#xff0c;找到因子个数恰好为 n n n​​​ 个的最小正整数. 保证答案不大于 1 e 18 1e18 1e18. 和 反素数 的思路是一样的&#xff0c;深搜 这个是枚举当前数字可以…

Shiro反序列化漏洞(CVE-2016-4437)+docker靶场+工具利用

一、Shiro反序列化漏洞-CVE-2016-4437原理 将java对象转换为字节序列&#xff08;json/xml&#xff09;的过程叫序列化&#xff0c;将字节序列&#xff08;json/xml&#xff09;恢复为java对象的过程称为反序列化。 Shiro框架提供了“记住我”的功能&#xff0c;用户登陆成功…

JPA 概述及常用注解详解、SpringDataJpa 使用指南

JPA&#xff08;Java Persistence API&#xff09;是 Java 标准中的一套ORM规范&#xff08;提供了一些编程的 API 接口&#xff0c;具体实现由 ORM 厂商实现&#xff0c;如Hiernate、TopLink 、Eclipselink等都是 JPA 的具体实现&#xff09;&#xff0c;借助 JPA 技术可以通过…

Unity3D 入门

文章目录 拖拽快捷键资源商店地形构建器 拖拽快捷键 首先看到Scene界面&#xff0c;我们布置游戏场景中的游戏对象基本是在这个界面完成的 鼠标滚轮键按住&#xff1a;能够拖拽平面&#xff0c;不移动对象鼠标右键按住&#xff1a;能够旋转我们观察界面的视角&#xff0c;不移…

快速理解并实现权限控制

什么是权限控制? 权限控制是指在一个系统或应用中对用户或角色的操作进行限制和管理的过程。它用于确保只有经过授权的用户或角色能够执行特定的操作或访问特定的资源。权限控制是信息安全和访问控制的重要组成部分。 权限控制的主要目的是保护系统的安全性和完整性&#xf…