【库函数】Linux下动态库.so和静态库.a的生成和使用

news2025/1/16 6:39:31

目录

🌞1. Linux下静态库和动态库的基本概念

🌞2. 动态库

🌊2.1 动态库如何生成

🌍2.1.1 文件详情

🌍2.1.2 编译生成动态库

🌊2.2 动态库如何使用

🌍2.2.1 案例

🌍2.2.2 动态库错误记录

🌞3. 静态库

🌊3.1 静态库如何生成

🌍3.1.1 文件详情

🌍3.1.2 编译生成动态库

🌊3.2 静态库如何使用


🌞1. Linux下静态库和动态库的基本概念

库(Library)是一组预先编写好的程序代码,它们被打包在一起以供其他程序使用,从而避免了重复编写相同的代码。库可以分为静态库和动态库两种类型:

静态库

  • 作用:在程序编译的时候,将库编译进可执行程序中, 运行的时候不需要外部函数库
  • 目录:默认库目录 /lib 或 /usr/lib 或 /usr/local/lib
  • 后缀:libxxx.a
  • 命名规范:静态库的名字一般为libxxxx.a,其中 xxxx 是该lib的名称

动态库

  • 作用:在程序运行的时候,将库加载到程序中,运行的时候需要外部函数库
  • 目录:默认的动态库搜索路径/lib;/usr/lib
  • 后缀:libxxx.so
  • 命名规范:动态库的名字一般为libxxxx.so.major.minor,xxxx 是该lib的名称,major是主版本号,minor是副版本号

使用库的主要目的是:

  1. 提高代码的重用性和可维护性
  2. 减少开发人员的工作量
  3. 并使程序更加模块化和易于扩展

常见的库包括:

  1. 标准库(如C标准库和C++标准库)
  2. 第三方库(如图形界面库、数据库访问库、网络通信库等)
  3. 自定义的库(根据项目需求编写的特定功能的库)

 对.h头文件的理解    传送门:【头文件】对.h文件的理解-CSDN博客


🌞2. 动态库

🌊2.1 动态库如何生成

下面通过一个小栗子介绍如何生成一个动态库。

  1. 一个头文件:  so_test.h
  2. 头文件接口实现的三个c文件:so_test_a.c  so_test_b.c  so_test_c.c
  3. 我们将这几个文件编译成一个动态库:libtest.so

🌍2.1.1 文件详情

我在路径/root/host/my_program/asoc/include下创建四个文件

一个头文件:

vi so_test.h
#ifndef SO_TEST_H
#define SO_TEST_H

int addTwoiNum(int a, int b);
int subTwoiNum(int a, int b);
int mulTwoiNum(int a, int b);

#endif

三个.c文件:

vi so_test_a.c
#include "so_test.h"
#include <stdio.h>

int addTwoiNum(int a, int b) {
    return a + b;
}
vi  so_test_b.c
#include "so_test.h"
#include <stdio.h>

int subTwoiNum(int a, int b) {
    return a - b;
}
vi so_test_c.c
#include "so_test.h"
#include <stdio.h>

int mulTwoiNum(int a, int b) {
    return a * b;
}

🌍2.1.2 编译生成动态库

给文件附上权限:

chmod 777 so_test_a.c so_test_b.c so_test_c.c so_test.h 

接下来,我们将编译这些文件成一个动态库。

在Linux系统中可以使用gcc来完成这个任务。

gcc -c -Wall -Werror -fpic so_test_a.c  so_test_b.c  so_test_c.c
gcc -shared -o libtest.so so_test_a.o so_test_b.o so_test_c.o

第一行命令 :

  • -c 选项告诉编译器只编译源文件,而不进行链接。
  • -fpic 选项用于生成与位置无关的代码,这是动态链接库所必需的。

第二行命令:

  • 使用 -shared 选项将目标文件链接成一个共享对象(动态库) libtest.so

现在,会得到一个名为 libtest.so 的动态库文件。


🌊2.2 动态库如何使用

前面已经成功生成了一个动态链接库libtest.so,下面通过一个程序来调用这个库里的函数。

比如程序的源文件为:main.c【我创建的目录是/root/host/my_program/asoc/my_program】

#include <stdio.h>
#include "so_test.h"

int main() {
    int result_a, result_b, result_c;
    int x = 10, y = 5;

    // 调用动态库中的函数
    result_a = addTwoiNum(x, y);
    result_b = subTwoiNum(x, y);
    result_c = mulTwoiNum(x, y);

    // 打印结果
    printf("Result of add: %d\n", result_a);
    printf("Result of sub: %d\n", result_b);
    printf("Result of mul: %d\n", result_c);

    return 0;
}

现在需要链接 libtest.so 到源文件。

下面是编译模板:

gcc -o main main.c -I/path/to/include -L/path/to/lib -ltest

模板参数说明:

  • -o main:指定输出文件的名称为 main
  • main.c:您的源文件。
  • -I/path/to/include:指定要搜索头文件的路径。
  • -L/path/to/lib:指定要搜索库文件的路径。
  • -ltest:指定要链接的库文件名称。这里假设动态库文件名为 libtest.so

请将 /path/to/include/path/to/lib 替换为实际的路径。


🌍2.2.1 案例

【案例】如果头文件路径是 /root/host/my_program/asoc/include/so_test.h,动态库文件路径是 /root/host/my_program/asoc/include/libtest.so,可以这样编译 main.c 文件:

gcc -o main main.c -I/root/host/my_program/asoc/include -L/root/host/my_program/asoc/include -ltest

在这个命令中:

  • -o main:指定输出文件的名称为 main
  • main.c:源文件。
  • -I/root/host/my_program/asoc/include:指定要搜索头文件的路径。
  • -L/root/host/my_program/asoc/include:指定要搜索库文件的路径。
  • -ltest:指定要链接的库文件名称。

链接完成会生成一个 main 的可执行文件,这个可执行文件到底有没有成功链接到动态链接库呢?

可以使用下面的命令来查看:

ldd main

这里说明虽然我们已经使用 -L 选项指定了库文件的搜索路径,但是系统加载器在搜索动态库时还是会按照默认的路径 /lib  或者 /usr/lib 的路径进行搜索,因此即使编译成功,但运行时仍找不到动态库。

要解决这个问题,可以尝试设置 LD_LIBRARY_PATH 环境变量来指定动态库的搜索路径。例如我的动态库.so是在路径/root/host/my_program/asoc/include下,则使用命令:

LD_LIBRARY_PATH=/root/host/my_program/asoc/include ./main

这样运行时就能够找到动态库 libtest.so+运行成功!


🌍2.2.2 动态库错误记录

这个错误是在动态库执行的时候经常会遇到,说找不到这个.so文件,如果放在/lib或者/usr/lib下,那么默认就能找到。如果放在其他目录下,有 3 种解决方案:

  1. 将.so 文件拷贝到 /usr/lib/文件夹下面
  2. 添加PATH环境变量【前面的案例就是使用这个解决】
    export LD_LIBRARY_PATH=<动态库所在的绝对路径>
  3. 修改配置脚本
    将动态库所在的路径加到  /etc/ld.so.conf 文件里
    vim /etc/ld.so.conf
    添加后刷新
    /sbin/ldconfig

🌞3. 静态库

🌊3.1 静态库如何生成

下面通过一个小栗子介绍如何生成一个静态库。

  1. 一个头文件:  vi staticlib.h
  2. 头文件接口实现的三个c文件:staticlib.c
  3. 我们将这几个文件编译成一个静态库:libstatic.a

🌍3.1.1 文件详情

我在路径/root/host/my_program/asoc/include下创建下面的文件

vi staticlib.h
#ifndef __STATICLIB_H
#define __STATICLIB_H

int hello();

#endif
vi staticlib.c
#include "staticlib.h"
#include <stdio.h>

int hello(){
    printf("hello,this is static lib\n");  
    return 0;
}

🌍3.1.2 编译生成动态库

给文件附上权限:

chmod 777 staticlib.h staticlib.c

使用编译器将 staticlib.c 编译成目标文件(.o 文件):

gcc -c staticlib.c -o staticlib.o

使用 ar 命令将目标文件打包成静态库文件 libstatic.a

ar rcs libstatic.a staticlib.o

这样就生成了名为 libstatic.a 的静态库文件,其中包含了 staticlib.o 的内容。


🌊3.2 静态库如何使用

前面已经成功生成了一个动态链接库libtest.so,下面通过一个程序来调用这个库里的函数。

比如程序的源文件为:test.c【我创建的目录是/root/host/my_program/asoc/my_program】

内容如下:

#include <stdio.h>
#include "staticlib.h"

int main() {
    printf("Calling hello() function...\n");
    hello();
    return 0;
}

接下来,需要编译 main.c 并链接静态库 libstatic.a

gcc test.c -o test -I/root/host/my_program/asoc/include/ -L/root/host/my_program/asoc/include/ -lstatic

参数说明:

  •  -L 参数指定了编译器搜索库文件的路径
  • -lstatic 指定了要链接的静态库名字(注意,lib 前缀和 .a 扩展名都不需要在此处指定)

然后运行可执行文件 test

./test

说明静态库链接成功!

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

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

相关文章

【jQuery】看一眼就会用的jquery库之续章!

jQuery&#xff08;js框架&#xff09; 17、操作节点 创建节点&#xff1a; 创建节点只需要将元素放在jQuery的工厂函数中//创建一个button按钮let $btn$("<input typebutton>");//创建一个列表项let $li$("<li>选项</li>");添加节点…

【PostgreSQL】Postgres数据库安装、配置、使用DBLink详解

目录 一、技术背景1.1 背景1.2 什么是 DBLink 二、安装配置 DBLink2.1 安装 DBLink2.2 配置 DBLink1. 修改 postgresql.conf2. 修改 pg_hba.conf 三、DBLink 使用3.1 数据准备3.2 DBLink 使用1. 创建 DBLink 连接2. 使用 DBLink 进行查询3. 使用 DBLink 进行增删改4. 使用 DBLi…

鲁棒控制理论学习:静态状态反馈H∞控制器

鲁棒性&#xff0c;即系统的健壮性&#xff0c;是指在异常和危险情况下系统能够维持其功能和性能的能力。在控制系统中&#xff0c;鲁棒性表现为系统在参数摄动下维持某些性能的特性。例如&#xff0c;当控制系统面临输入错误、磁盘故障、网络过载或有意攻击等挑战时&#xff0…

视频质量评价PSNR的两种计算方法

PSNR&#xff08;峰值信噪比&#xff09; 峰值信号的能量与噪声的平均能量之比&#xff0c;本质的是比较两张图像像素值差异&#xff0c;用途较广&#xff0c;目前仍作为对照其他指标的基线。PSNR的单位是dB&#xff0c;数值越大表示失真越小。 mn单色图像 I 和K&#xff0c; …

SpringCloud系列(17)--将服务消费者Consumer注册进Zookeeper

前言&#xff1a;在上一章节中我们把服务提供者Provider注册进了Zookeeper&#xff0c;而本章节则是关于如何将服务消费者Consumer注册进Zookeeper 1、再次创建一个服务提供者模块&#xff0c;命名为consumerzk-order80 (1)在父工程下新建模块 (2)选择模块的项目类型为Maven并…

WIFI加密方式对无线速率的影响

文章目录 无线加密三种选择&#xff1a;WEP、WPA和WPA2测试平台和测试方法非加密和WEP加密测试 结果差别巨大非加密条件下 300M无线路由实测WEP加密条件下 300M无线路由实测 TKIP加密算法&#xff1a;WPA与WPA2成绩低迷WPA加密&#xff08;TKIP加密算法&#xff09;条件下 300M…

TypeScript入门第一天,所有类型+基础用法+接口使用

表示逻辑值&#xff1a;true 和 false。在JavaScript和TypeScript里叫做boolean | | 数组类型 | 无 | 声明变量为数组。 // 在元素类型后面加上[] let arr: number[] [1, 2]; // 或者使用数组泛型&#xff0c;Array<元素类型> let arr: Array [1, 2]; | | 元组…

大数据—数据采集DataX

一、DataX介绍 官网&#xff1a; DataX/introduction.md at master alibaba/DataX GitHub DataX 是阿里云 DataWorks数据集成 的开源版本&#xff0c;在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。 DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、…

翻译《The Old New Thing》 - Why .shared sections are a security hole

Why .shared sections are a security hole - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20040804-00/?p38253 Raymond Chen 2004年08月04日 许多人会推荐使用共享数据节作为在应用程序的多个实例之间共享数据的一种方式。这听起来是个好…

立即刷新导致请求的response没有来得及加载造成的this request has no response data available

1、前端递归调用后端接口 const startProgress () > {timer.value setInterval(() > {if (progress.value < 100) {time.value--;progress.value Math.ceil(100 / wait_time.value);} else {clearInterval(timer.value);progress.value 0;timer.value null;time.…

pytest-asyncio:协程异步测试案例

简介&#xff1a;pytest-asyncio是一个pytest插件。它便于测试使用异步库的代码。具体来说&#xff0c;pytest-asyncio提供了对作为测试函数的协同程序的支持。这允许用户在测试中等待代码。 历史攻略&#xff1a; asyncio并发访问websocket Python&#xff1a;协程 - 快速创…

vscode安装中文插件不生效

在 escode 中&#xff0c;安装了上面的插件&#xff0c;但是界面依然显示的是英文。 解决方案 使用组合键 ctrshiftp&#xff0c;输入 Configure Display Language&#xff0c; 选中 zh-cn&#xff0c;重启

机器视觉3D视觉检测系统的优势

随着科技的飞速发展&#xff0c;机器视觉技术已经成为现代工业生产中不可或缺的一部分。特别是3D视觉检测系统&#xff0c;其优势日益凸显&#xff0c;为各行业的质量控制和生产自动化提供了强大的支持。本文将探讨机器视觉3D视觉检测系统的优势&#xff0c;并分析其在实际应用…

C语言入门课程学习笔记-6

C语言入门课程学习笔记-6 第27课 - 字符数组与字符串&#xff08;上&#xff09;第28课 - 字符数组与字符串&#xff08;下&#xff09;第29课 - 数组专题练习&#xff08;上&#xff09;第30课 - 数组专题练习&#xff08;下&#xff09; 本文学习自狄泰软件学院 唐佐林老师的…

【图像压缩算法】霍夫曼编码

1. 研究背景 霍夫曼在1952年提出一种构造最佳码的方法&#xff0c;称之为霍夫曼编码&#xff08;Huffman)。霍夫曼编码是一种无损的统计编码方法&#xff0c;利用信息符号概率分布特性的改变字长进行编码。霍夫曼编码适用于多元独立信源&#xff0c;对于多元独立信源来说它是最…

淘宝API接口大全:淘宝app商品详情数据接口

淘宝APP商品详情数据接口是用于获取商品详情信息的专用API&#xff0c;适用于移动应用开发者使用。 要使用这个接口&#xff0c;你需要遵循以下步骤&#xff1a; 了解和申请API权限&#xff1a;在使用淘宝API接口之前&#xff0c;需要先前往淘宝开放平台了解相关的API文档&am…

Git泄露和hg泄露原理理解和题目实操

一.Git泄露 1.简介 Git是一个开源的分布式版本控制系统&#xff0c;它可以实现有效控制应用版本&#xff0c;但是在一旦在代码发布的时候&#xff0c;存在不规范的操作及配置&#xff0c;就很可能将源代码泄露出去。那么&#xff0c;一旦攻击者发现这个问题之后&#xff0c;就…

速卖通自养号测评:如何规避安全风险?

对于初涉电商领域的新卖家而言&#xff0c;进行销量测评显得尤为关键。由于速卖通新店铺往往难以获得平台活动的支持&#xff0c;流量也相对匮乏&#xff0c;因此&#xff0c;开店的首要任务便是进行测评&#xff0c;通过积累一定的评论和销售数据。 测评的益处颇多&#xff0…

Java web应用性能分析之【sysbench基准测试】

Java web应用性能分析之【CPU飙高分析之MySQL】-CSDN博客 Java web应用性能分析之【Linux服务器性能监控分析概叙】-CSDN博客 Java web应用性能分析概叙-CSDN博客 Java web应用性能分析之【基准测试】-CSDN博客 上面基本科普了一下基准测试&#xff0c;这里我们将从sysbench…

leetCode60. 排列序列

leetCode60. 排列序列 方法一:语法版&#xff0c;面试官不认可的方法&#xff1a;next_permutation函数 // 方法一&#xff1a;使用next_permutation函数&#xff0c;将某容器设置为当前按照字典序 // 的下一个全排列的内容 class Solution { public:string getPermutation(in…