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

目录

🌞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

说明静态库链接成功!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TCP详解

2.1TCP 由IETF的RFC793定义的传输控制协议&#xff08;Transmission Control Protocol&#xff0c;TCP&#xff09;是一种基于字节流的传输层通信协议。在传输数据前需要在发送与接收者之间建立连接&#xff0c;通过相应机制保证其建立连接的可靠性。 TCP协议具备以下特性&am…

云备份项目->配置环境

升级gcc到7.3版本 sudo yum install centos-release-scl-rh centos-release-scl sudo yum install devtoolset-7-gcc devtoolset-7-gcc-c source /opt/rh/devtoolset-7/enable echo "source /opt/rh/devtoolset-7/enable" >> ~/.bashrc 安装Jsoncpp库 sud…

十、多模态大语言模型(MLLM)

1 多模态大语言模型&#xff08;Multimodal Large Language Models&#xff09; 模态的定义 模态&#xff08;modal&#xff09;是事情经历和发生的方式&#xff0c;我们生活在一个由多种模态(Multimodal)信息构成的世界&#xff0c;包括视觉信息、听觉信息、文本信息、嗅觉信…

STM32与Proteus的串口仿真详细教程与源程序

资料下载地址&#xff1a;STM32与Proteus的串口仿真详细教程与源程序 资料内容 包含LCD1602显示&#xff0c;串口发送接收&#xff0c;完美实现。 文档内容齐全&#xff0c;包含使用说明&#xff0c;相关驱动等。 解决了STM32的Proteus串口收发问题。 注意&#xff1a;每输…

IP-guard getdatarecord 存在任意文件读取

声明 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 一、产品介绍 IP-guard是由溢信科技股份有限公司开发的一款终端安全管…

揭秘被忽视的商业模式:全民拼购助力客户实现日销千万的惊人业绩

今天&#xff0c;我想和大家分享一个颇具潜力的模式与玩法&#xff0c;尽管它在外界看来可能略显陈旧。这个模式曾被忽视&#xff0c;但我的一位客户却巧妙运用&#xff0c;实现了惊人的业绩——日销售额接近五千万&#xff0c;日订单量高达300万单。 值得注意的是&#xff0c;…

一键搞定COX回归亚组森林图!快速生成顶级SCI论文的高清图!

现在亚组分析好像越来越流行&#xff0c;无论是观察性研究还是RCT研究&#xff0c;亚组分析一般配备森林图。 比如NEJM这张图&#xff1a; 比如Lancet这张图&#xff1a; 但是在使用R语言绘制时&#xff0c;简单的代码画不出好看的图&#xff0c;好看的图又需要许多代码参数来进…

[HUBUCTF 2022 新生赛]最简单的misc

有点简单&#xff0c; 要用到工具lsb&#xff0c;qr扫码 一般杂项先binwalk&#xff0c;不行的话在lsb 因为头是png所以save bin出二维码&#xff0c;用QR扫码 即可得出flag

知识分享之cookie

http协议中的cookie&#xff0c;什么是cookie如何获取cookie 一、什么是Cookie Cookie&#xff08;曲奇&#xff0c;小甜饼的译名&#xff09;在互联网技术领域中&#xff0c;是指一种小型文本文件&#xff0c;它由网站服务器发送给用户的浏览器&#xff0c;并被浏览器存储在用…

Linux--自主编写shell

目录 准备知识 shell原理 shell与用户互动的过程 实现shell 0.用到的头文件和宏定义 1.首先我们需要自己输出一个命令行 2.获取用户命令行字符 3.命令行字符串分割 4.执行命令 5.设置循环 6.检测内建命令 7.完善细节--获取工作目录而非路径 准备知识 Linux--环境…

太速科技-基于6 U VPX M.2 高带宽加固存储板

基于6 U VPX M.2 高带宽加固存储板 一、板卡概述 基于6 U VPX M.2 高带宽加固存储板&#xff0c;可以实现VPX接口的数据读写到PCI-E总线的NVME存储媒介上。采用PLX8732&#xff0c;上行链路提供带宽x16的PCI-E数据到VPX接口上&#xff1b;下行链路提供3路带宽x4的PCI-E接口…

重生之我是Nginx服务专家

nginx服务访问页面白色 问题描述 访问一个域名服务返回页面空白&#xff0c;非响应404。报错如下图。 排查问题 域名解析正常&#xff0c;网络通讯正常&#xff0c;绕过解析地址访问源站IP地址端口访问正常&#xff0c;nginx无异常报错。 在打开文件时&#xff0c;发现无法…

(学习日记)2024.05.04:UCOSIII第五十八节:User文件夹函数概览(uCOS-III->Source文件夹)第四部分

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

自制音频格式二维码的方法,适合多种音频格式使用

现在可以通过二维码的方法来传递音频文件是很常用的一种方式&#xff0c;可以将单个或者多个音频放入一个二维码&#xff0c;通过手机扫码来调取云端储存的音频文件来播放内容&#xff0c;这样可以让多人同时扫码获取内容&#xff0c;提升传播速度。 音频二维码制作的方法也比…

数据库 和 SQL 和 索引事务 和 Java数据库编程(JDBC)

一、初识数据库 什么是数据库&#xff1f;和数据结构有什么关系&#xff1f; 数据库是“一类软件”&#xff0c;能够针对数据进行管理。数据结构&#xff0c;也是针对数据进行管理。所以&#xff0c;数据库其实就是一个“基于数据结构”实现出来的软件。 有哪些常用数据库&…

Postman,一个功能强大的API开发和测试工具

最近有小伙伴说在找 postman 的使用教程&#xff0c;案例等文章。 那么今天我就来写一个。 Postman 是一个功能强大的 API 开发和测试工具&#xff0c;它提供了丰富的功能&#xff0c;帮助开发人员更好地管理、测试和文档化 API。无论是单独开发还是团队协作&#xff0c;Postma…

社交媒体数据恢复:MiChat

在数字化时代&#xff0c;我们的生活与社交媒体平台紧密相连&#xff0c;如MiChat等即时通讯应用成为沟通的桥梁。然而&#xff0c;数据丢失的风险始终存在&#xff0c;使得“及时备份”这一概念愈发重要。当用户不慎删除了珍贵的聊天记录时&#xff0c;他们可能会感到绝望。幸…

Xcode隐私协议适配

1. Privacy manifest files 1.1 简介 自己App或三方SDK&#xff08;通过XCFrameworks|Swift packages|Xcode projects集成的&#xff09;需要包含一个隐私清单文件&#xff08;privacy manifest&#xff09;叫作 PrivacyInfo.xcprivacy。它是一个属性列表&#xff0c;记录了A…

Spring一篇搞定!控制反转特性(IOC)详细笔记

控制反转&#xff08;IOC&#xff09; 是什么 控制反转&#xff08;Inversion of Control&#xff0c;IoC&#xff09;是一种设计思想&#xff0c;它的本质是将对象的创建、销毁、依赖关系的维护等控制权从程序代码中转移出去&#xff0c;交由容器来负责管理。在Java开发中&a…

多种方法求1+12+123+1234……

有网友出了一道题&#xff1a; 从键盘输入一个小于10的正整数n&#xff0c;计算1121231234……&#xff0c;即前n项之和。 第一眼看到题目&#xff0c;直觉告诉我必须使用嵌套的两个for循环&#xff0c;里面的循环生成每一项&#xff0c;外面的循环求和。错误的方向和思路让我…