【Hello Linux】动态库和静态库(下)

简介: 【Hello Linux】动态库和静态库(下)

静态库的打包和使用

我们下面使用静态库打包和使用的例子让大家更加深入的理解静态库

我们使用下面的四个文件来演示

add.h

1 #pragma once 
  2                                                   
  3 extern int myadd(int x , int y);

add.c

1 #include "add.h"  
  2   
  3 int myadd(int x , int y)  
  4 {  
  5   return x + y;                                   
  6 } 

sub.h

1 #pragma once 
  2 
  3 extern int mysub(int x , int y);  

sub.c

1 #include "sub.h"
  2 
  3 int mysub(int x , int y)
  4 {
  5   return x-y;                                     
  6 }

打包

第一步 生成二进制文件

第二步 将所有目标文件打包为静态库

ar命令是gnu的归档工具 常用于将目标文件打包为静态库

下面是命令选项

  • -r(replace):若静态库文件当中的目标文件有更新 则用新的目标文件替换旧的目标文件
  • -c(create):建立静态库文件
  • -t:列出静态库中的文件
  • -v(verbose):显示详细的信息

我们可以使用下面的指令将一个或多个目标文件打包为静态库

ar -rc libst.a add.o sub.o

我们可以使用下面的指令查看一个静态库中的文件

ar -tv libst.a

第三步 将头文件和生成的动态库组织起来

与我们使用时一样

我们可以将所有的头文件放到 /include 文件夹中

将所有的静态库文件放到 /lib 文件夹中

接着将这两个目录放到 /mylib

这样子我们就可以将我们的mylib给别人使用了

使用

我们首先写出一个源文件 main.c

1 #include <stdio.h>
E>  2 #include <add.h>
E>  3 #include <sub.h>
    4 
    5 
    6 
    7 int main()
    8 {
    9   int x = 10;                                                                                            
   10   int y = 20;
E> 11   int z1 = myadd(x , y);
E> 12   int z2 = mysub(x , y);
   13   printf ("myadd :: %d\n" , z1);
   14   printf ("mysub :: %d\n" , z2);
   15   return 0;
   16 

我们发现 这个源文件中其实报了四个错误 这是因为我们c语言程序在查到头文件的时候只会查找同级的头文件还有系统配置的头文件

而我们当前目录下只有两个文件 main.c 和 mylib

不过我们不必担心 编译之后的程序肯定是可以正常运行的

使用方式一: 使用选项

gcc编译时我们需要使用的三个选项如下

  • -I:指定头文件搜索路径
  • -L:指定库文件搜索路径
  • -l:指明需要链接库文件路径下的哪一个库

所以说我们只需要敲出下面的指令他就可以

gcc -o main main.c -I ./mylib/include/ -L ./mylib/lib/ -l st

这段指令的意思是使用main.c源程序编译 指定某个头文件 指定某个库文件 指定st这个库

编译生成一个名为main的可执行文件

这个时候我们就可以运行我们的程序了

使用方式二: 把头文件和库文件拷贝到系统路径下

编译器之所以能够找到c的头文件和库文件是因为它们被放在默认的路径中

当我们开始编译的时候编译器就会默认去那里寻找

而头文件的默认路径在这里

/usr/include/

而库文件的默认路径在这里

/lib64/

所以说我们只需要将自己的头文件和库文件拷贝到这两个地方就可以了

我们使用下面两个指令来拷贝

cp ./mylib/include/* /usr/include/
cp ./mylib/lib/libst.a /lib64/

之后我们再看main文件代码

我们发现这次代码并没有报错

但是我们这里发现gcc编译的时候报错了 这是因为gcc编译的时候默认找的是c库 而我们添加的库并不是c库

所以说我们编译的时候还需要指定依赖的库文件

注意: 我十分不建议将自己写的库文件拷贝到系统路径中 这样子会污染原本的库文件

动态库的打包和使用

我们还是使用这四个库文件来演示动态库的打包和使用

打包

第一步 生成对应的目标文件

让所有源文件生成对应的目标文件

动态库与静态库汇编指令中不同的是 动态库的汇编指令中需要加上-fPIC选项

-fPIC选项的意义是生成和位置无关码

它是一个很复杂的概念 涉及到很多的专业知识 这里就不过多赘述 对于它我们只需要了解两点

  1. -fPIC作用于编译阶段 告诉编译器产生与位置无关的代码 之后代码被加载到内存的任何位置都可以运行
  2. -fPIC选项并不是必须要加的 如果不加动态库必须要在加载到用户程序的地址空间时重定向所有表目

第二步 打包动态库

与生成静态库时使用ar命令打包不同 我们只需要使用gcc的-shared选项即可

指令如下

gcc -shared -o libdy.so add.o sub.o

第三步 将头文件和生成的动态库组织起来

和生成的静态库一样

我们可以将所有的头文件放到 /include 文件夹中

将所有的静态库文件放到 /lib 文件夹中

接着将这两个目录放到 /mylib

这样子我们就可以将我们的mylib给别人使用了

使用

我们还是使用静态库的源文件main.c来演示动态库的使用

1 #include <stdio.h>
E>  2 #include <add.h>
E>  3 #include <sub.h>
    4 
    5 
    6 
    7 int main()
    8 {
    9   int x = 10;
   10   int y = 20;
E> 11   int z1 = myadd(x , y);
E> 12   int z2 = mysub(x , y);
   13   printf ("myadd :: %d\n" , z1);
   14   printf ("mysub :: %d\n" , z2);
   15   return 0;                                                            
   16 }

动态库的编译方法和静态库的编译方法一模一样

我们可以使用指令或者是将库文件和头文件放到系统目录中

我们这里使用指令为例

我们敲出下面的指令就可以编译

我们发现这样子就生成了我们的可执行程序了

但是和静态库的使用不一样 使用动态库的文件在成为可执行文件的时候还不能直接运行

我们再使用ldd指令 查看这个可执行文件所依赖的动态库

我们发现系统找不到这个动态库在哪里

这是因为 我们使用-I,-L,-l这三个选项都是在编译期间告诉编译器我们使用的头文件和库文件在哪里以及是谁 但是当生成的可执行程序生成后就与编译器没有关系了

所以说如果我们想要执行这个程序 还需要想办法告诉操作系统这个库文件的地址

这里有三种方式可以做到

方式一 拷贝到系统路径下

我们直接将该动态库拷贝到系统的库文件目录下 这样子操作系统就能够找到了

指令如下

cp ./mlib/dylib/libdy.so /lib64

这样子就可以顺利运行了

方式二 更改环境变量

LD_LIBRARY_PATH是程序运行动态查找库时所要搜索的路径 我们只需将动态库所在的目录路径添加到LD_LIBRARY_PATH环境变量当中即可

使用指令如下

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/shy/linux/lesson11~20/lesson13/code4/mlib/dylib/

之后我们再查询a.out的动态库 可以发现

我们可以发现动态库的路径变为了我们设置的路径

当然现在也可以继续运行了

方式三 配置/etc/ld.so.conf.d/

我们可以通过配置/etc/ld.so.conf.d/的方式解决该问题

首先我们自己需要写一个以.conf后缀的文件

将我们库文件所在的路径放到这个文件当中

之后将这个配置文件放到 /etc/ld.so.conf.d/ 目录中

之后使用指令更新配置文件

ldconfig

这样子我们就可以运行我们的文件了

投票

相关文章
|
23天前
|
存储 编译器 Linux
动态链接的魔法:Linux下动态链接库机制探讨
本文将深入探讨Linux系统中的动态链接库机制,这其中包括但不限于全局符号介入、延迟绑定以及地址无关代码等内容。
308 22
|
5月前
|
安全 Linux vr&ar
Linux的动态库和静态库
Linux的动态库和静态库
|
3月前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
119 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
5月前
|
Linux API
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
在Linux中,程序产生了库日志虽然删除了,但磁盘空间未更新是什么原因?
|
6月前
|
Oracle 关系型数据库 Linux
讲解linux下的Qt如何编译oracle的驱动库libqsqloci.so
通过这一连串的步骤,可以专业且有效地在Linux下为Qt编译Oracle驱动库 `libqsqloci.so`,使得Qt应用能够通过OCI与Oracle数据库进行交互。这些步骤适用于具备一定Linux和Qt经验的开发者,并且能够为需要使用Qt开发数据库应用的专业人士提供指导。
188 1
讲解linux下的Qt如何编译oracle的驱动库libqsqloci.so
|
5月前
|
Linux 网络安全 API
【Azure 应用服务】App Service For Linux 环境中,如何从App Service中获取GitHub私有库(Private Repos)的Deploy Key(RSA key)呢?
【Azure 应用服务】App Service For Linux 环境中,如何从App Service中获取GitHub私有库(Private Repos)的Deploy Key(RSA key)呢?
|
5月前
|
小程序 Linux 开发者
Linux之缓冲区与C库IO函数简单模拟
通过上述编程实例,可以对Linux系统中缓冲区和C库IO函数如何提高文件读写效率有了一个基本的了解。开发者需要根据应用程序的具体需求来选择合适的IO策略。
39 0
|
6月前
|
Linux 编译器 vr&ar
【Linux】静态库和动态库
本文详细介绍了Linux系统中静态库和动态库的概念、区别、制作与使用方法,包括它们在链接时的区别、加载机制以及优缺点。
88 0
|
2月前
|
Linux 网络安全 数据安全/隐私保护
Linux 超级强大的十六进制 dump 工具:XXD 命令,我教你应该如何使用!
在 Linux 系统中,xxd 命令是一个强大的十六进制 dump 工具,可以将文件或数据以十六进制和 ASCII 字符形式显示,帮助用户深入了解和分析数据。本文详细介绍了 xxd 命令的基本用法、高级功能及实际应用案例,包括查看文件内容、指定输出格式、写入文件、数据比较、数据提取、数据转换和数据加密解密等。通过掌握这些技巧,用户可以更高效地处理各种数据问题。
138 8
|
2月前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
555 6