【Linux系统编程】第三十二弹---动态库实战指南:从零构建与高效集成的奥秘

news2024/12/1 0:32:24

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】【Linux系统编程】

目录

1、动态库 

1.1、怎么做动态库

1.2、怎么使用动态库 

2、外部库使用


1、动态库 

1.1、怎么做动态库

方式一

1、将.c文件编译成.o文件

[jkl@host lib]$ gcc -c mystdio.c
[jkl@host lib]$ gcc -c mymath.c
[jkl@host lib]$ ls
libmyc.a  mylib     mymath.h  mystdio.c  mystdio.o 
main.c    mymath.c  mymath.o  mystdio.h  roommate   

2、将.o文件打包成动态库文件 

[jkl@host lib]$ gcc *.o -o libmyc.so
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

[jkl@host lib]$ gcc -shared *.o -o libmyc.so
/usr/bin/ld: mystdio.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
  • shared: 表示生成共享库格式

上面的方式不能打包成动态库文件,需要在编译成.o文件时加选项

方式二

1、删除前面编译的.o文件

[jkl@host lib]$ rm *.o
[jkl@host lib]$ ls
libmyc.a  main.c  mylib  mymath.c  mymath.h  mystdio.c  mystdio.h  roommate  

 2、将.c文件编译成.o文件(加选项)

[jkl@host lib]$ gcc -fPIC -c mymath.c
[jkl@host lib]$ gcc -fPIC -c mystdio.c
[jkl@host lib]$ ls
libmyc.a  mylib     mymath.h  mystdio.c  mystdio.o  
main.c    mymath.c  mymath.o  mystdio.h  roommate   
  • fPIC:产生位置无关码(position independent code)。这种代码可以在运行时被加载到内存中的任何位置,而不需要对代码本身进行修改。

3、将.o文件打包成动态库文件 

[jkl@host lib]$ gcc -shared *.o -o libmyc.so
[jkl@host lib]$ ls
libmyc.a   main.c  mymath.c  mymath.o   mystdio.h  roommate  
libmyc.so  mylib   mymath.h  mystdio.c  mystdio.o  

1.2、怎么使用动态库 

1、先将动态库文件拷贝到lib目录下

[jkl@host lib]$ cp libmyc.so mylib/lib
[jkl@host lib]$ tree mylib
mylib
|-- include
|   |-- mymath.h
|   `-- mystdio.h
`-- lib
    |-- libmyc.a
    `-- libmyc.so

2 directories, 4 files

2、 通过命令编译文件

[jkl@host roommate]$ gcc main.c -I mylib/include -L mylib/lib -lmyc
[jkl@host roommate]$ ls
a.out  log.txt  main.c  mylib
[jkl@host roommate]$ ./a.out
./a.out: error while loading shared libraries: libmyc.so: cannot open shared object file: No such file or directory
[jkl@host roommate]$ ldd a.out
	linux-vdso.so.1 =>  (0x00007ffde21da000)
	libmyc.so => not found
	libc.so.6 => /lib64/libc.so.6 (0x00007f4245348000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f4245716000)

 没有找到这个动态库文件,原因是:动态库在程序运行的时候,要找到动态库加载并运行

为什么静态库没有找不到文件的问题?

编译期间,已经将库中的代码拷贝到我们的可执行程序内部了!加载和库没有关系了,这也是为什么静态库所占内存空间比动态库大很多的原因。

解决办法一

将动态库安装到系统中(不推荐)。

[jkl@host roommate]$ sudo cp mylib/lib/libmyc.so /lib64 # 将动态库文件拷贝到系统中,普通用户需要使用sudo提权
[sudo] password for jkl: 
[jkl@host roommate]$ gcc main.c -I mylib/include -L mylib/lib -lmyc # 默认使用动态库编译
[jkl@host roommate]$ ls
a.out  log.txt  main.c  mylib
[jkl@host roommate]$ ./a.out # 执行代码
10 + 20  = 30
[jkl@host roommate]$ ldd a.out
	linux-vdso.so.1 =>  (0x00007fff79128000)
	libmyc.so => /lib64/libmyc.so (0x00007fdef1f1b000) # 我们拷贝的动态库
	libc.so.6 => /lib64/libc.so.6 (0x00007fdef1b4d000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fdef211d000)
[jkl@host roommate]$ file a.out 
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=37f079df869cdf34f19759f0317a0da027a1973a, not stripped

删除拷贝的动态库文件 

[jkl@host roommate]$ sudo rm /lib64/libmyc.so # 删除动态库文件
[jkl@host roommate]$ ll /lib/libmyc.so  # 查看前面拷贝的动态库文件,确认删除
ls: cannot access /lib/libmyc.so: No such file or directory
[jkl@host roommate]$ ./a.out # 删除之后就运行不了,不需要重新编译
./a.out: error while loading shared libraries: libmyc.so: cannot open shared object file: No such file or directory

解决办法二

建立软链接。

[jkl@host roommate]$ sudo ln -s /home/jkl/linux-learning/lib/roommate/mylib/lib/libmyc.so /lib64/libmyc.so # 将自己的动态库文件软链接到系统的同名文件
[jkl@host roommate]$ ll /lib64/libmyc.so # 查看软链接文件
lrwxrwxrwx 1 root root 57 Sep 10 14:06 /lib64/libmyc.so -> /home/jkl/linux-learning/lib/roommate/mylib/lib/libmyc.so
[jkl@host roommate]$ ./a.out # 运行程序
10 + 20  = 30
[jkl@host roommate]$ ldd a.out
	linux-vdso.so.1 =>  (0x00007ffd94fc9000)
	libmyc.so => /lib64/libmyc.so (0x00007f31209de000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f3120610000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f3120be0000)

取消软链接

[jkl@host roommate]$ sudo unlink /lib64/libmyc.so # 取消软链接
[jkl@host roommate]$ ll /lib64/libmyc.so # 查看软链接文件,没有该文件
ls: cannot access /lib64/libmyc.so: No such file or directory
[jkl@host roommate]$ ./a.out # 程序执行不了
./a.out: error while loading shared libraries: libmyc.so: cannot open shared object file: No such file or directory

解决办法三

命令行导入环境变量(内存级别的,退出就没有该环境变量了)

[jkl@host roommate]$ LD_LIBRARY_PATH=$LD_LIBARY_PATH:/home/jkl/linux-learning/lib/roommate/mylib/lib
[jkl@host roommate]$ echo $LD_LIBRARY_PATH
:/home/jkl/.VimForCpp/vim/bundle/YCM.so/el7.x86_64:/home/jkl/linux-learning/lib/roommate/mylib/lib
[jkl@host roommate]$ ./a.out
10 + 20  = 30
[jkl@host roommate]$ ldd
[jkl@host roommate]$ ldd a.out
	linux-vdso.so.1 =>  (0x00007ffe06fcf000)
	libmyc.so => /home/jkl/linux-learning/lib/roommate/mylib/lib/libmyc.so (0x00007f7dcb53e000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f7dcb170000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f7dcb740000)

退出xshell

[jkl@host roommate]$ echo $LD_LIBRARY_PATH
:/home/jkl/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
[jkl@host roommate]$ ./a.out
./a.out: error while loading shared libraries: libmyc.so: cannot open shared object file: No such file or directory

解决办法四

修改.bashrc配置文件,让环境变量永久生效。

1、编辑.bashrc文件

[jkl@host ~]$ vim .bashrc
[jkl@host ~]$ source ~/.bashrc # 立即生效

注意:如果环境变量没有生效退出XShell重新登录即可。 

 2、执行代码

[jkl@host roommate]$ echo $LD_LIBRARY_PATH 
:/home/jkl/.VimForCpp/vim/bundle/YCM.so/el7.x86_64:/home/jkl/linux-learning/lib/roommate/mylib/lib
[jkl@host roommate]$ ./a.out
10 + 20  = 30
[jkl@host roommate]$ ldd a.out
	linux-vdso.so.1 =>  (0x00007ffcfdfe7000)
	libmyc.so => /home/jkl/linux-learning/lib/roommate/mylib/lib/libmyc.so (0x00007f638dac1000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f638d6f3000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f638dcc3000)

3、将路径从文件中删除。

[jkl@host ~]$ cat .bashrc
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
	. /etc/bashrc
fi

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

# User specific aliases and functions
alias vim='/home/jkl/.VimForCpp/nvim'
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/.VimForCpp/vim/bundle/YCM.so/el7.x86_64

解决办法五

/etc/ld.so.conf.d 新增动态库搜索的配置文件,ldconfig生效。

 1、在/etc/ld.so.conf.d 目录下新增一个.conf结尾的文件,内容为动态库文件所在目录(需要root权限)

[jkl@host ~]$ cd /etc/ld.so.conf.d # 进入目录
[jkl@host ld.so.conf.d]$ ls
bind-export-x86_64.conf  dyninst-x86_64.conf  kernel-3.10.0-1160.108.1.el7.x86_64.conf  mysql-x86_64.conf
[jkl@host ld.so.conf.d]$ sudo touch mylib.conf # 创建文件需要提权
[sudo] password for jkl: 
[jkl@host ld.so.conf.d]$ ls
bind-export-x86_64.conf  dyninst-x86_64.conf  kernel-3.10.0-1160.108.1.el7.x86_64.conf  mylib.conf  mysql-x86_64.conf
[jkl@host ld.so.conf.d]$ sudo vim mylib.conf
[jkl@host ld.so.conf.d]$ sudo ldconfig # 让动态链接库为系统所共享

 2、执行代码

[jkl@host roommate]$ ./a.out
10 + 20  = 30
[jkl@host roommate]$ ldd
ldd: missing file arguments
Try `ldd --help' for more information.
[jkl@host roommate]$ ldd a.out
	linux-vdso.so.1 =>  (0x00007fffacf78000)
	libmyc.so => /home/jkl/linux-learning/lib/roommate/mylib/lib/libmyc.so (0x00007f48d1437000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f48d1069000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f48d1639000)

动静态库总结

动静态库的最终意义还是提高开发效率。 

2、外部库使用

系统中其实有很多库,它们通常由一组互相关联的用来完成某项常见工作的函数构成。
比如用来处理屏幕显示情况的函数(ncurses库)

#include <math.h>
#include <stdio.h>
int main()
{
  double x = pow(2.0, 3.0);
  printf("The cubed is %f\n", x);
  return 0;
}

使用外部库链接 

[jkl@host lib]$ gcc -Wall calc.c -o calc -lm
[jkl@host lib]$ ldd calc
	linux-vdso.so.1 =>  (0x00007ffdf00a1000)
	libm.so.6 => /lib64/libm.so.6 (0x00007fb17991b000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fb17954d000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fb179c1d000)
[jkl@host lib]$ ./calc
The cubed is 8.000000

有链接到外部库。 

  • lm表示要链接libm.so或者libm.a库文件

库文件名称和引入库的名称

  • 如:libc.so -> c库,去掉前缀lib,去掉后缀.so,.a

直接编译

[jkl@host lib]$ gcc calc.c
[jkl@host lib]$ ./a.out
The cubed is 8.000000
[jkl@host lib]$ ldd a.out
	linux-vdso.so.1 =>  (0x00007fffb4359000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f2081cb1000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f208207f000)

可执行程序的结果是一样的,只是链接到的库有差别。 

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

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

相关文章

创客项目秀|基于XIAO ESP32C3的Night Lamp With Chinese Traditional Pane项目

Fab Academy&#xff0c;源自麻省理工学院的先进教育项目&#xff0c;致力于培养具有全球视野的创新者和制造者。通过密集学习和实践&#xff0c;学生们掌握了从基础到高级的制造技术&#xff0c;学习了如何将创意转化为现实。今天小编给大家带来的是Fab academy学员Dion Tsang…

前端全栈混合之路Deno篇:Deno2.0与Bun对比,谁更胜一筹?或者说谁更适合怎样的项目

在前端全栈开发中&#xff0c;工具的不断演变让开发者们始终在寻找更高效、更现代化的解决方案。继Node.js之后&#xff0c;Deno和Bun 成为了两个比较火热的运行时。Deno2.0的近期的发布让它在性能和兼容性方面大幅提升-尤其是兼容了npm包&#xff08;但我感觉应该不是全部兼容…

如何给低代码平台取名?命名策略与技巧全解析

低代码平台正日益成为企业数字化转型的重要工具。为了确保您的平台能够脱颖而出&#xff0c;吸引到更多的用户和开发者&#xff0c;选择一个恰到好处的名字至关重要。本文将探讨如何为您的低代码平台选择一个既独特又易于记忆的好名字&#xff0c;并详细介绍一系列行之有效的命…

第二百七十九节 JPA教程 - JPA查询IN一对多示例

JPA教程 - JPA查询IN一对多示例 以下JPQL显示如何在一对多映射中使用IN运算符。 executeAndPrintQuery("SELECT DISTINCT p FROM Employee e, IN(e.directs) p");例子 下面的代码来自Department.java。 package cn.w3cschool.common;import java.util.ArrayList; …

中药药材推荐系统

毕业设计还在发愁选题&#xff1f;又想实用又怕复杂&#xff1f;那这篇介绍你一定感兴趣&#xff01; 今天为大家推荐一个基于Django框架开发的中药药材推荐系统&#xff0c;简洁易用&#xff0c;功能丰富&#xff0c;非常适合毕业设计。无论你是技术经验丰富的开发人员&#…

praat语音标注

一、软件下载 praat软件下载链接 下载后双击 二、软件界面

【机器学习】朴素贝叶斯算法|商品评论情感分析案例介绍及代码实现

文章目录 朴素贝叶斯算法朴素贝叶斯算法介绍概率数学基础复习朴素贝叶斯算法-利用概率值进行分类的一种机器学习算法贝叶斯公式朴素贝叶斯算法拉普拉斯平滑系数 朴素贝叶斯API案例分析流程数据集代码实现运行结果 朴素贝叶斯算法 朴素贝叶斯算法介绍 概率数学基础复习 条件概…

扇形旋转切换效果(等级切换转盘)

实现动态扇形旋转切换效果&#xff0c;切换进度支持渐变效果 效果展示 在线示例 https://code.juejin.cn/pen/7425559403589271588 源码实现 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"v…

华宇携司法大模型亮相2024中国移动全球合作伙伴大会

2024中国移动全球合作伙伴大会于10月11日在广州琶洲保利世贸博览馆盛大开幕。本届大会以“智焕新生 共创AI时代”为主题&#xff0c;深入探讨数据、算力与人工智能如何深度融合&#xff0c;全力推进AI规模发展、规模应用&#xff0c;加快形成AI技术能力、经济效益上的规模效应&…

【NestJS入门到精通】装饰器

目录 方法装饰器通过prototype添加属性、方法 属性装饰器拓展 方法装饰器参数装饰器 方法装饰器 ClassDecorator 定义了一个类装饰器 a&#xff0c;并将其应用于类 A。装饰器 a 会在类 A 被定义时执行。 const a:ClassDecorator (target:any)>{console.log(target,targe…

Python Django 数据库优化与性能调优

Python Django 数据库优化与性能调优 Django 是一个非常流行的 Python Web 框架&#xff0c;它的 ORM&#xff08;对象关系映射&#xff09;允许开发者以简单且直观的方式操作数据库。然而&#xff0c;随着数据量的增长&#xff0c;数据库操作的效率可能会成为瓶颈&#xff0c…

【SQL Server】数据库在新建查询后闪退——解决方案:以管理员的身份运行

我的SQLServer2022之前都是可以用的&#xff0c;隔了好久没有使用&#xff0c;今天要用到去写一些SQL 语句 结果在点击新建查询后闪退了&#xff0c; 经过查询后&#xff0c;解决方案&#xff1a; 以管理员的身份运行后点击新建查询&#xff0c;发现正常了 总结&#xff1a;以…

PyQt 入门教程(2)搭建开发环境

文章目录 一、搭建开发环境1、安装PyQt6与pyqt6-tools2、配置外部工具QtDesigner与PYUIC 一、搭建开发环境 1、安装PyQt6与pyqt6-tools PyQt6&#xff1a; PyQt的开发库。pyqt6-tools&#xff1a; QtDesigner 设计器支撑库。 通过PyCharm安装开发库&#xff0c;命令如下&…

探索全流量回溯分析系统:IT运维的必备利器

目录 一、什么是全流量回溯分析系统&#xff1f; 二、全流量回溯分析系统的核心功能 三、IT运维中的实际应用案例 四、IT运维中使用全流量回溯分析系统的技巧 结语 AnaTraf 网络性能监控系统NPM | 全流量回溯分析 | 网络故障排除工具 在当今的IT运维中&#xff0c;网络故…

【Python爬虫实战】正则:多字符匹配、开头与结尾定位、分组技术详解

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、匹配多个字符 &#xff08;一&#xff09;匹配任意多个字符 &#xff0…

OpenAI Canvas:提升编程与写作效率的全新工作界面

随着人工智能技术的飞速发展&#xff0c;大语言模型&#xff08;LLM&#xff09;不仅限于生成文本&#xff0c;还能逐步扩展至编程、设计等任务的支持。近期&#xff0c;OpenAI 推出了一个名为 Canvas 的全新功能&#xff0c;专门用于协助用户进行编程和写作。这一功能与 Claud…

请求参数中字符串的+变成了空格

前端请求 后端接收到的结果 在URL中&#xff0c;某些字符&#xff08;包括空格、、&、? 等&#xff09;需要被编码。具体而言&#xff0c;在URL中&#xff0c;空格通常被编码为 或 %20。因此&#xff0c;如果你在请求参数中使用 &#xff0c;它会被解释为一个空格。 如果…

C++ | Leetcode C++题解之第473题火柴拼正方形

题目&#xff1a; 题解&#xff1a; class Solution { public:bool makesquare(vector<int>& matchsticks) {int totalLen accumulate(matchsticks.begin(), matchsticks.end(), 0);if (totalLen % 4 ! 0) {return false;}int len totalLen / 4, n matchsticks.s…

lstm和informer和gru模型对比

1 介绍 本文使用数据集&#xff0c;对三个模型进行了对比&#xff0c;代码使用python完成&#xff0c;通过对比&#xff0c;发现lstm>gru>informer. 2 数据读取 使用降水量数据集&#xff0c;第一列表示降水&#xff0c;第二列表示出水量。 输入是两个特征输出是一个…

百度视觉搜索架构演进实践

本文深入探讨百度视觉搜索在快速发展的业务及技术背景下&#xff0c;如何通过持续的技术创新和架构升级强化自身的竞争力和适应性&#xff0c;支撑业务健康高效迭代。本文介绍了我们如何通过技术栈升级、架构能力提升以及稳定性建设&#xff0c;来实现全链路架构的演进。借助Go…