【Linux】静动态库的制作和使用

news2024/12/23 5:09:12

前言

        好久不见,甚是想念~ 

        本篇文章具体以操作为主,介绍在Linux下如何打包动静态库,并且如何使用这些库,同时,简单的阐述一下原理。让我们开始吧~

上一篇Linux文章传送地址~

【Linux】基础IO的理解与操作 - fd_柒海啦的博客-CSDN博客_io中 fd

[我们经历的每个日常也许就是连续不断的奇迹。]

目录

一、我们为什么需要库?

二、静态库 .a/.lib

1.代码实例(包含.h 和 .c 文件)

        sort.h文件

        sort.c文件

2.静态库的制作

3.使用静态库

1使用系统的默认路径:

2指定路径:

三、动态库 .so/.dll

1.制作动态库

1生成无序二进制文件:

 2GCC/G++生成动态库:

2.使用动态库


一、我们为什么需要库?

        在日常程序中,我们难免会经常使用一些重复性的代码:比如方法(函数)printf、cout、scanf、cin等;或者容器 vector、queue、stack、unordered_map等。

        这些在使用过程中,难道每次一个使用项目的时候就要手动去导入这些代码或者去写吗?那样的话效率十分低下。

        所以,站在写库的角度上看:1.简单。2.代码安全。并且,库的存在,可以大大的减少开发周期,并且提高了软件本身的质量。

        那么库也分为两种,一种就是静态库,另一种就是动态库静态库程序在编译链接的过程中将库的代码链接到可执行文件中。程序运行的时候就不再需要静态库。动态库则是程序在运行的时候采取链接动态库的代码,多个程序可以共享使用库的代码

二、静态库 .a/.lib

        在Linux下,静态库的扩展名为.a,windows下扩展名为.lib

        我们以下面这段排序算法的代码为例,来进行静态的库的生成和使用。

1.代码实例(包含.h 和 .c 文件)

        sort.h文件

// sort.h
#pragma once 
#include <iostream>
#include <assert.h>
#include <string.h>

using std::cout;
using std::cin;
using std::endl;

namespace YuShen
{
  // 堆排
  void HeapSort(int* arr, int len);
  void AdjustDown(int* arr, int len, int parent);
  // 归并排序
  void _MergeSort(int* arr, int* tmp, int begin, int end);
  void MergeSort(int* arr, int len);
  void MergeSortNoRecursive(int* arr, int len);  // 非递归实现
  // 快速排序
  void QuickSort(int* arr, int len);
  void _quickSort(int* arr, int begin, int end);
  int _quickSort1(int* arr, int begin, int end);  // 原始版本实现
  int _quickSort2(int* arr, int begin, int end);  // 挖坑版本实现
  int _quickSort3(int* arr, int begin, int end);  // 双指针版本实现
}

        sort.c文件

// sort.c
#include "sort.h"

void YuShen::AdjustDown(int* arr, int len, int parent)
{
  int child = parent * 2 + 1;
  while (child < len)
  {
    if (child + 1 < len && arr[child] < arr[child + 1]) ++child;
    if (arr[parent] < arr[child])
    {
      std::swap(arr[parent], arr[child]);
      parent = child;
      child = parent * 2 + 1;
    }
    else break;
  }
}

void YuShen::HeapSort(int* arr, int len)
{
  assert(arr);
// 向下调整
  for (int i = (len - 2) / 2; i >= 0; --i) AdjustDown(arr, len, i);
  for (int i = 0; i < len; i++)
  {
    std::swap(arr[0], arr[len-1-i]);
    AdjustDown(arr, len-1-i, 0);
  }
}



void YuShen::MergeSort(int* arr, int len)
{
    //....
}

void YuShen::MergeSortNoRecursive(int* arr, int len)
{
    //...
}

int YuShen::_quickSort1(int* arr, int begin, int end)
{
  // 原始版本
    //......
}
int YuShen::_quickSort2(int* arr, int begin, int end)
{
  // 挖坑版本
    //......
}

int YuShen::_quickSort3(int* arr, int begin, int end)
{
  // 双指针版本
    //......
}

void YuShen::_quickSort(int* arr, int begin, int end)
{
  if (begin >= end) return;
  int trage = _quickSort3(arr, begin, end); 
  _quickSort(arr, begin, trage - 1);
  _quickSort(arr, trage + 1, end);
}
void YuShen::QuickSort(int* arr, int len)
{
  assert(arr);
  _quickSort(arr, 0, len - 1);
}

2.静态库的制作

命令:

        ar -rc lib[静态库名字].a .o文件

解释:

      ar:是gnu归档工具,详细可以参考此网址GNU工具链 - surferqing - 博客园 (cnblogs.com)

      -rc:(replace and create)替换和创建,意思就是把后面的所有.o文件打包成一个静态库。

      lib[].a: []里面为自定义名字。前缀必须为lib,后缀必须为.a文件。

      .o文件: 需要打包的.o文件集(中间用空格间隔)。必须是.o文件,因为静态库的本质就和在和程序文件编译的最后一步链接和主程序进行链接。所以必须是经过-c即汇编操作形成的.o文件。

        比如,我们将上面的代码文件打包成静态库.a。

        首先,将目标文件的源程序编译为.o文件。即反汇编操作变成二进制文件。

g++ -o sort.o sort.cpp -c

         然后就可以将.o文件打包成静态库,使用ar归档工具:

ar -rc libsort.a sort.o

 

         实际上,我们通常使用库的时候,.a文件放在一个文件夹(lib),.h文件放在一个文件夹(include),方便文件查找或者进行分类,所以这里我们也可以这样进行操作。利用makefile进行脚本操作:

libsort.a:sort.o
	ar -rc libsort.a sort.o
	make sort
sort.o:sort.cpp
	g++ -c $^ -o $@
.PHONY:sort 
sort:
	mkdir ./include
	mkdir ./lib 
	mkdir ./tempfile
	cp *.h include 
	mv libsort.a lib
	mv *.o tempfile
.PHONY:clean 
clean:
	make clean-sort
	make clean-test
.PHONY:clean-sort 
clean-sort:
	rm -rf include 
	rm -rf lib 
	rm -rf tempfile 
.PHONY:clean-test 
clean-test:
	rm -f test

         上面我们.o文件放在临时文件夹内的,其实如何脚本操作完全可以看你自己的想法。运行一下make脚本:

         制作成功后,如何将静态库添加到程序文件内呢(即含有main函数的程序入口)?

3.使用静态库

1使用系统的默认路径

        头文件gcc的默认搜索路径是:/user/include
        云服务器库文件默认搜索路径:/lib64

        自己所写的库属于第三方库 -- 不是语言和操作系统自带的,C语言的默认静态库是libc.a编译C语言会默认链接。如果直接拷贝过去还是会链接不了,需要告诉GCC    gcc [...]  -l库名

         但是一般不推荐上述做法,因为自己写的不一定通过代码的考验,没有经过测试的库或者软件安装在系统路径下的话有时出现问题不好解决。

2指定路径

        这种方法保险。但是操作相对麻烦,下面先介绍方法:

g++/gcc [-o ... ... .cpp/.c] -I 头文件路径(.h) -L 库文件路径(.a) -l库名

选项解释:

        -I i的大写,表示include,即搜索头文件从当前目录进行搜索

        -L l的大写,表示lib,即搜索库文件从当前目录进行搜素

        -l库名 l的小写,库名表示指定链接库。

路径-相对和绝对路径均可。

        由此,我们利用下面这个测试程序,将我们上面生成的静态库进行链接:

        test.cpp文件

// test.cpp
#include "sort.h"

int main()
{
  int arr[] = {3, 6, 2, 1, 4, 10, 9, 5, 7, 8};
  int len = sizeof(arr) / sizeof(arr[0]);
  for (int i = 0; i < len; ++i) cout << arr[i] << " ";
  cout << endl;
  YuShen::HeapSort(arr, len);
  for (int i = 0; i < len; ++i) cout << arr[i] << " ";
  cout << endl;
  return 0;
}

         静态库链接,编译,运行:

g++ -o test test.cpp -I ./include -L ./lib -lsort -std=c++11

         静态库可以使用。

三、动态库 .so/.dll

        在Linux下动态库扩展名为.so,windows为.dll

        动态库可以理解为编译好的一块程序加载入内存。因为首先在内存中存在了这样的一块程序,那么多个程序都可以共享这一块程序,通过进程地址空间中的共享区。这样的话动态库的效率就会很高,并且生成出来的可执行程序也不会很大。

1.制作动态库

        动态库制作和静态库类似,只不过不使用ar进行规整,而是通过gcc/g++进行编译生成。

1生成无序二进制文件

        首先通过选项-fPIC 生成无序的程序二进制文件(汇编步骤-c),至于为什么可以参考这篇文章:

linux编译动态库之fPIC - 知乎 (zhihu.com)

g++ -o sort.o -c sort.cpp -fPIC

 2GCC/G++生成动态库

        通过选项-shared(共享)生成动态库,可-o选项指定lib库名.so生成动态库文件。

g++ -shared sort.o -o libsort.so

         和静态库类似,我们也可以将头文件放入include目录,库文件放入lib目录。

2.使用动态库

1拷贝到系统路径下

        和静态库类似,不推荐。

2临时加载入环境变量

        利用命令行export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:绝对路径(到库路径下)添加此库的路径,就可链接上动态库:

3修改配置文件

        创建 /etc/ld.so.conf.d/名字.conf。将动态库路径放入此路径即可。ldconfig  -- 配置文件生效一下。

4建立软链接解决

        或者使用和静态库类似的方法,也就是直接链接:

g++ -o test2 test.cpp -I ./include -L ./lib -lsort

        假设test1是先前我们链接静态库后的可执行文件。ldd命令可以查看程序链接的相关库,我们可以看到:

        默认链接的是动态库。即存在同名静动态库的话。当然,如果强制链接静态库,可以加上-static。 

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

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

相关文章

复合材料专场 | ABAQUS车载四型复合材料气瓶固化过程的数值模拟分析攻略

复合材料气瓶固化的热场本质上可以认为包含两个阶段&#xff0c;复合材料气瓶表面和周围通过与空气的热对流换热&#xff0c;复合材料与内部塑料芯模以及金属接头的传热。在第一个阶段整体温度较低&#xff0c;热量从表面向复合材料层内部流入&#xff0c;此时固化速率很低&…

Python使用Opencv图像处理方法完成手势识别(三)tkinter制作GUI界面

前面对手势识别已经差不多完成。 这一章来制作一个手势识别GUI界面和说一下精确度不够问题所在。 首先是精确度不够的问题&#xff1a; 让手势更规范&#xff0c;手掌张开点。首先应该调节Hsv阈值&#xff0c;因为手掌和环境颜色与我的可能有差异。调整面积&#xff0c;周长阈…

ADI Blackfin DSP处理器-BF533的开发详解7:SPI接口的驱动和应用(含源代码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 接口功能介绍 SPI 接口是 4 线串口&#xff0c;可以连接 SPIFLASH&#xff0c;SPI 接口的 AD&#xff0c;DA 等等。ADSP-BF533 的 SPI 接口支持主…

【Python合集系列】爬虫有什么用,网友纷纷给出自己的答案,王老师,我..我想学那个..爬虫。可以嘛?“(代码免费分享)

导语 Hello&#xff0c;大家好呀&#xff01;我是木木子吖&#xff5e; 一个集美貌幽默风趣善良可爱并努力码代码的程序媛一枚。 听说关注我的人会一夜暴富发大财哦~ &#xff08;哇哇哇 这真的爱&#x1f60d;&#x1f60d;&#xff09; 生活中总有些东西值得爬一爬 爬虫…

Java 内存模型之 JMM

—— 计算机存储结构 计算机存储结构&#xff0c;从本地磁盘到主存到 CPU 缓存&#xff0c;也就是硬盘到内存&#xff0c;到CPU&#xff0c;一般对应的程序的操作就是从数据库到内存然后到CPU进行计算CPU拥有多级缓存&#xff0c;&#xff08;CPU和物理主内存的速度不一致&…

群集搭建【LNMP+负载均衡+高可用+跳板机】

目录 项目需求 LNMP部署 web1部署 mysql部署 php部署 nfs部署 LNMP测试 负载均衡与高可用 web2部署 lb1部署 lb2部署 验证群集 跳板机功能 测试跳板机 项目需求 实验目标&#xff1a;根据拓扑图搭建环境&#xff0c;安装论坛&#xff0c;创建证书通过https访问&#xff0c;实现…

一文搞懂 Nginx

文章目录一、前言二、NGINX 指令与上下文2.1 指令2.2 上下文三、NGINX 静态文件处理3.1 静态文件配置3.2 静态文件类型处理四、NGINX 动态路由4.1 Location 匹配4.1.1 前缀匹配4.1.2 精准匹配4.1.3 正则匹配4.1.4 优先前缀匹配4.2 Location 匹配优先级4.2.1 匹配优先级对比4.2.…

学好selenium工具,能实现你想得到的所有事情

文章目录一、介绍背景二、开发与实现2.1、部署开发环境2.2、开始码代码<demo只为提供思路>2.3、思路分析2.4、难点解析三、总结一、介绍背景 情况是这样的&#xff1a;某段时间之前&#xff0c;开发想找我用ui自动化帮他们实现一个功能&#xff1a;在系统某些时候生成报告…

[附源码]计算机毕业设计大学生心理健康测评系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

零基础CSS入门教程(17)——内边距

本章目录1.任务目标2.默认情况3.有内边距4.小结1.任务目标 上一篇介绍了外边距&#xff0c;也就是元素跟相邻元素的距离。 本篇来介绍内边距&#xff0c;顾名思义&#xff0c;内边距是指的元素内部的内容&#xff0c;与元素的边的距离 2.默认情况 <!DOCTYPE html> <…

Velero 系列文章(一):基础

概述 Velero 是一个开源工具&#xff0c;可以安全地备份和还原&#xff0c;执行灾难恢复以及迁移 Kubernetes 集群资源和持久卷。 灾难恢复 Velero 可以在基础架构丢失&#xff0c;数据损坏和/或服务中断的情况下&#xff0c;减少恢复时间。 数据迁移 Velero 通过轻松地将 …

使用VictoriaMetrics 对Prometheus的数据进行分布式存储

前言 Prometheus 就是一个很好的时序数据库&#xff0c;对于监控数据量没有超过千万级的 情况下没必要进行分布式存储。一般的监控数据存3个月以内即可&#xff0c;所以数据量并不会很大。 并且生产环境可以搞多个Proms数据源在Grafana中做统一的告警。并且在时序数据库的排名…

windows安装minikube

由于学习的需要&#xff0c;需要在windows上搭建一套可以使用的k8s学习用&#xff0c;最后选择了minikube这个安装k8s&#xff0c;本博客介绍了minikube的安装步骤&#xff0c;详细命令以及截图 1、首先是本机windows安装docker&#xff0c;具体可以参考这个 win10安装docker…

奥曲肽-葡聚糖-亲和索的偶联物TOC-Dx40-Av)|紫杉醇-DHA-右旋糖酐偶联聚合物

中文名称&#xff1a;奥曲肽-葡聚糖-亲和索的偶联物 英文名称&#xff1a;TOC-Dx40-Av 纯度&#xff1a;95% 存储条件&#xff1a;-20C&#xff0c;避光&#xff0c;避湿 外观:固体或粘性液体 包装&#xff1a;瓶装/袋装 溶解性&#xff1a;溶于大部分有机溶剂&#xff0…

GC 算法总结_java培训

1.标记清除压缩(Mark-Sweep-Compact) 标记清除、标记压缩的结合使用 原理java培训GC 算法总结 2.算法总结 内存效率&#xff1a;复制算法>标记清除算法>标记整理算法&#xff08;此处的效率只是简单的对比时间复杂度&#xff0c;实际情况不一定如此&#xff09;。 内…

城市云灾备,为业务连续性保驾护航

摘要&#xff1a;华为云作为中国政务云基础设施领域领导者&#xff0c;基于华为公有云技术架构的政务云平台&#xff0c;具备领先的云灾备技术实力&#xff0c;支持IaaS、PaaS等云服务云原生灾备能力。本文分享自华为云社区《城市云灾备&#xff0c;为业务连续性保驾护航》&…

Delphi Base64 的“坑”

使用 Delphi 原生的Base64编码&#xff08;System.NetEncoding 单元&#xff09; &#xff0c;编码后的字符串每隔76个字符会增加一个回车换行&#xff08;#13#10&#xff09;&#xff0c;这样就导致和其他语言对接的时候出现问题&#xff0c;特别是Base64以后再进行签名&#…

元学习:IVIF:输入不同分辨率,输出任意分辨率

Different Input Resolutions and Arbitrary Output Resolution: A Meta Learning-Based Deep Framework for Infrared and Visible Image Fusion &#xff08;不同的输入分辨率和任意输出分辨率: 基于元学习的红外和可见光图像融合深度框架&#xff09; 在本文中&#xff0c…

Web大学生网页作业成品——城市环卫管理系统后台模板(HTML+CSS+JavaScript)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

浏览器中的音视频知识总结v1.0(工作中需要和视频打交道必看)

视频是什么 视频&#xff0c;其实就是一系列连续播放的图片&#xff0c;如果1s钟播放24张图片&#xff0c;那么人眼看到的就不再是一张张独立的图片&#xff0c;而是动起来的画面。其中一张图片称为一帧&#xff0c;1s播放的图片数称为帧率。常见的帧率有24帧/s&#xff0c;30帧…