关键词:
文章目录
前言
下面的所有操作的的操作都是基于:
- 操作系统:
Ubuntu20.04.3-desktop
- GCC-Version:
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
- G+±Version:
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
一、库文件
- 库文件是计算机上的一类文件,可以简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数或类。
- 库是特殊的一种程序,编写库的程序和编写一般的程序区别不大
- 库文件有两种,静态库 和 动态库(共享库),区别是:静态库在程序的链接阶段被复制到了程序中;动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。
- 库的好处:代码保密 和 方便部署和分发
程序编译的过程:
二、静态库
2.1 命名规则
- 对于
Linux
平台的话,一般为:libxxx.a
lib
:固定前缀xxx
:自定义的名称.a
:固定后缀
例如有一个静态库的名称:libhello.a
- 对于
Windows
平台的话,一般为:libxxx.lib
lib
:固定前缀xxx
:自定义的名称.lib
:固定后缀
2.2 静态库的制作
静态库的制作过程:
制作静态库我们需要用到一个打包工具:ar
(archive)
ar
可以将一些 .o
文件打包成一个 .a
静态库
使用方法如下:
ar rcs libxxx.a xxx.o xxx.o……
这里我们举一个例子:
假设我们当前有三个文件:add.c
、plus.c
、head.h
然后我们先将这两个.c
文件编译、汇编成.o
文件,然后再使用ar
打包
gcc -c add.c plus.c
此时我们就会生成 add.o
和 plus.o
文件,然后我们使用ar
命令
ar rcs libcalc.a add.o plus.o
此时我们发现生成了一个 libcalc.a
的文件,注意的是静态库代码中使用到的头文件也需要一并发送,所以我们一般将头文件集中管理,于是创建一个include
文件夹
mkdir include
mv *.h include/
同样为了方便管理静态库文件,我们也创建一个lib
文件夹
mkdir lib
mv *.a lib/
此时我们的目录结构应该是这样的
2.3 静态库的使用
现在我们再新建一个main.c
文件,测试一下我们的这个静态库
touch main.c
然后写点简单的内容:
#include <stdio.h>
#include <head.h>
int main()
printf("%d\\n",add(1,2));
printf("%d\\n",multiply(3,4));
return 0;
然后我们再编译一下:
gcc -o main main.c -I ./include -l calc -L lib
其中-l
是指定链接库的名字,而-L
表示在哪个地方去找库,-I
表示的是头文件引用的位置
此时我们就生成了一个可执行程序main
,我们试着运行:./main
这就是一个简单的静态库的打包和使用啦~
三、动态库
3.1 命名规则
- 对于
Linux
平台的话,一般为:libxxx.so
lib
:固定前缀xxx
:自定义的名称.so
:固定后缀
例如有一个静态库的名称:libhello.a
- 对于
Windows
平台的话,一般为:libxxx.dll
lib
:固定前缀xxx
:自定义的名称.dll
:固定后缀
3.2 动态库的制作
动态库的制作过程:
有了上面静态库的学习,动态库的制作其实类似,只不过编译动态库的时候全程使用gcc
步骤主要分为两步:
- 通过
gcc
生成与位置无关的.o
文件
仍然使用上面的.c
文件(当然这里可以先将.o
文件都删掉:rm *.o
)加上-fpic
选项生成与位置无关的 .o
文件
为什么要用-fpic
呢?
因为
-fpic
用于编译阶段,产生的代码没有绝对地址,全部用相对地址,这正好满足了共享库的要求,共享库被加载时地址不是固定的。如果不加-fpic
,那么生成的代码就会与位置有关,当进程使用该.so
文件时都需要重定位,且会产生成该文件的副本,每个副本都不同,不同点取决于该文件代码段与数据段所映射内存的位置
gcc -c -fpic add.c plus.c -I include/
- 通过
gcc
生成动态库
gcc -shared add.o plus.o -o libcalc.so
此时我们就生成了一个libcalc.so
的动态库文件
3.3 动态库的使用
我们将 libcalc.so
移动到 lib
目录,并且删除libcalc.a
静态库
mv libcalc.so ./lib
rm ./lib/libcalc.a
此时我们的目录结构如下:
这个main
可执行文件是上面的,我们可以先将其删除:rm main
然后我们编译main.c
:
gcc -o main main.c -I include -L lib -l calc
此时我们又生成了main
的可执行文件
我们试着直接运行,会发现遇到这样的错误:
./main: error while loading shared libraries: libcalc.so: cannot open shared object file: No such file or directory
其实就是程序运行的时候并未加载到动态库,导致了运行出错
对于动态库而言,程序启动后,动态库会被动态加载到内存中,通过 ldd
(list dynamic dependencies
)命令检查动态库依赖关系
例如我们这里通过ldd main
来查看main
可执行文件的依赖动态库
我们发现此时的libcalc.so
是一个not found
的情况,所以我们需要在动态库的加载路径上将我们的libcalc.so
拷贝过去
首先我们要清楚,动态库如何定位到共享文件?
当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路
径。此时就需要系统的动态载入器来获取该绝对路径。对于elf
格式的可执行程序,是
由ld-linux.so
来完成的,它先后搜索elf
文件的 DT_RPATH
段 ——> 环境变量LD_LIBRARY_PATH
——> /etc/ld.so.cache
文件列表 ——> /lib/
,/usr/lib
目录找到库文件后将其载入内存。
流程图:
3.3.1 修改环境变量
新增一行数据:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/mangata/Learn_C++/Linux_study/class2/lib
LD_LIBRARY_PATH
后面跟的是动态库的绝对路径
然后在终端输入source .bashrc
激活环境变量
然后此时我们通过ldd
查看main
就已经链接上了
3.3.2 修改/etc/ld.so.cache文件列表
因为该文件是一个二进制文件,不好直接更改,所以我们更改/ect/ld.so.conf
文件,在文件末尾加上lib
的路径
然后出来在终端输入sudo ldconfig
使其生效
3.3.3 /lib或/usr/lib目录
所以我们可以将libcalc.so
拷贝到/usr/lib
目录
sudo cp lib/libcalc.so /usr/lib
此时我们再来通过ldd
查看main
文件:
我们发现:libcalc.so => /lib/libcalc.so (0x00007effed09d000)
也就是说此时的动态库是能找到了
于是我们运行./main
四、动静态库的优缺点
4.1 静态库
优点:
- 静态库被打包到应用程序中加载速度快
- 发布程序无需提供静态库,移植方便
缺点:
- 消耗系统资源,浪费内存
- 更新、部署、发布麻烦
4.2 动态库
优点:
- 可以实现进程间资源共享(共享库)
- 更新、部署、发布简单
- 可以控制何时加载动态库
缺点:
- 加载速度比静态库慢
- 发布程序时需要提供依赖的动态库
linux下c/c++编程开发静态库和动态库(代码片段)
文章目录前言一、库文件二、静态库2.1命名规则2.2静态库的制作2.3静态库的使用三、动态库3.1命名规则3.2动态库的制作3.3动态库的使用3.3.1修改环境变量3.3.2修改/etc/ld.so.cache文件列表3.3.3/lib或/usr/lib目录四、动静态库的优缺点4.1... 查看详情
《python开发-python杂记》python与c/c++混合编程(代码片段)
Python是脚本语言,可以做的事情非常的多,本文将要讲解使用Python来调用C/C+库。关于C/C++库的创建请看笔者以前的文章,这里只给出Window下的创建过程。静态库和动态库(Windows版)静态库和动态库(Linux版)1Windows... 查看详情
《python开发-python杂记》python与c/c++混合编程(代码片段)
Python是脚本语言,可以做的事情非常的多,本文将要讲解使用Python来调用C/C+库。关于C/C++库的创建请看笔者以前的文章,这里只给出Window下的创建过程。静态库和动态库(Windows版)静态库和动态库(Linux版)1Windows... 查看详情
linux下intel的mkl编程代码,怎么样编译。c++和c语言代码
...L/lib/-l库名当然前提该库是路径在/lib/的想要在linux下学习编程,建议把linux编程学好。以上实在linux终端下实现本回答被提问者和网友采纳 查看详情
linux下动态库和静态库制作与调用
Linux下动态库和静态库制作与调用1.动态库和静态库简介 静态库是指在应用中,有一些公共代码需要反复使用,就把这些代码编译为“库”文件;在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文... 查看详情
cgo静态库和动态库(代码片段)
CGO静态库和动态库CGO在使用C/C++资源的时候一般有三种形式:直接使用源码;链接静态库;链接动态库。直接使用源码就是在import"C"之前的注释部分包含C代码,或者在当前包中包含C/C++源文件。链接静态库和动态库的方式... 查看详情
linux下的动态库和静态库详解(代码片段)
...要使用别人(一般是顶尖的工程师写的)的代码?为了开发效率和鲁棒性(健壮性)如何使用别人的功能?1、库2、开源代码3、基本的网络功能调用(各自网络接口,语音识别)库一般分为动态库和静态库,动态库一般的... 查看详情
动态库和静态库(代码片段)
前提:本文是基于Linux系统下的编程与学习补充:头文件卫士,避免头文件重复包含。//头文件卫士#ifndef__HEAD_H__#define__HEAD_H__//头文件内容#endif//__HEAD_H__命令:nmnm 二进制文件名; 可以查看二进制文件的符号表那... 查看详情
linux环境下的静态链接库和动态链接库(代码片段)
什么是链接库计算机中,有些文件专门用于存储可以重复使用的代码块,例如功能实用的函数或者类,我们通常将它们称为库文件,简称“库”(Library)。以C语言为例,如下为大家展示的就是一个函数库://myMath.cintadd(inta,intb)r... 查看详情
linux静态库和共享(动态)库的创建与使用详解(代码片段)
...代码的可重用性,而且还可以提高程序的健壮性;可以减少开发者的代码开发量,缩短开发周期.库制作完成后,如何给用户使用头文件—包含了库函数的声明库文件—包含了库函数的代码实现注意:库不能单独使用,只能作为其他执行... 查看详情
详解linux下静态库/动态库的生成和使用(含代码示例和操作流程)&&动态库和静态库的区别(代码片段)
文章目录一、库的概念Windows的库Linux的库二、动态库和静态库的区别1.载入顺序不同2.大小与共享的差异3.库函数调用的差异三、静态库的创建和使用1.创建静态库的步骤:(一)ar命令的使用方法(二)生成静... 查看详情
《c语言杂记》静态库和动态库(linux版)(代码片段)
1静态库和动态库概述库是一种软件组件技术,库里面封装了数据和函数。库的使用可以使程序模块化。库有两种:静态库和动态库。Windows系统包括静态链接库(.lib文件)和动态链接库(.dll文件)。Linux通... 查看详情
《c语言杂记》静态库和动态库(linux版)(代码片段)
1静态库和动态库概述库是一种软件组件技术,库里面封装了数据和函数。库的使用可以使程序模块化。库有两种:静态库和动态库。Windows系统包括静态链接库(.lib文件)和动态链接库(.dll文件)。Linux通... 查看详情
静态库和动态库编程技术
(1)库一、什么是库 库从本质上来说是一种代码重用的方式,即预先编译可执行代码的二进制格式,可以被载入内存中,执行,比如C运行库,里面实现了基本的函数,我们无需在写一遍,直接调用接口即可.库分为静态库和... 查看详情
linux静态库和动态库编译的区别
Linux库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。例如:libhello.solibhello.a为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如:libhello.so.1.0,由于程序连接默认以.so为文件后缀名。所以... 查看详情
linux动态库和静态库(代码片段)
文章目录动静态库的基本原理认识动静态库动静态库各自的特征静态库的打包与使用打包使用动态库的打包与使用打包使用动静态库的基本原理动静态库的本质是可执行程序的“半成品”。我们都知道,一堆源文件和头文件... 查看详情
第1章linux系统编程入门:静态库和动态库的对比
文章目录程序编译成可执行程序的过程静态库制作过程动态库的制作过程静态库的优缺点动态库的优缺点程序编译成可执行程序的过程静态库、动态库区别来自链接阶段如何处理,链接成可执行程序。分别称为静态链接方式... 查看详情
windows和linux下的目标文件静态库和动态库
Windows和Linux下的目标文件、静态库和动态库一、.obj.lib.dll使用在windows平台下:.obj:目标文件,相当于源代码对应的二进制文件,未经重定位。.lib:可理解为多个obj的集合,本质与.obj相同。.dll:动态... 查看详情