【C语言学习笔记】:动态库

news2024/11/15 10:48:23

一、动态库

通过之前静态库那篇文章的介绍。发现静态库更容易使用和理解,也达到了代码复用的目的,那为什么还需要动态库呢?

1、为什么还需要动态库?

为什么需要动态库,其实也是静态库的特点导致。

▶ 空间浪费是静态库的一个问题。

▶ 另一个问题是静态库对程序的更新、部署和发布页会带来麻烦。如果静态库liba.lib更新了,所以使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)。

动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。

动态库特点总结:

    ✪ 动态库把对一些库函数的链接载入推迟到程序运行的时期。

    ✪ 可以实现进程之间的资源共享。(因此动态库也称为共享库)

    ✪ 将一些程序升级变得简单。

    ✪ 甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。

Window与Linux执行文件格式不同,在创建动态库的时候有一些差异。

    ✪ 在Windows系统下的执行文件格式是PE格式,动态库需要一个DllMain函数做出初始化的入口,通常在导出函数的声明时需要有_declspec(dllexport)关键字。

    ✪ Linux下gcc编译的执行文件默认是ELF格式,不需要初始化入口,亦不需要函数做特别的声明,编写比较方便。

与创建静态库不同的是,不需要打包工具(ar、lib.exe),直接使用编译器即可创建动态库。

2、Linux下创建与使用动态库

linux动态库的命名规则为:

动态链接库的名字形式为 libxxx.so,前缀是lib,后缀名为“.so”。

    ✪ 针对于实际库文件,每个共享库都有个特殊的名字“soname”。在程序启动后,程序通过这个名字来告诉动态加载器该载入哪个共享库。

    ✪ 在文件系统中,soname仅是一个链接到实际动态库的链接。对于动态库而言,每个库实际上都有另一个名字给编译器来用。它是一个指向实际库镜像文件的链接文件(lib+soname+.so)。

3、创建动态库(.so)

编写四则运算动态库代码:

#pragma onceclass DynamicMath{public:        DynamicMath(void);        ~DynamicMath(void);        static double add(double a, double b);        static double sub(double a, double b);        static double mul(double a, double b);        static double div(double a, double b);        void print();};

首先,生成目标文件,此时要加编译器选项-fpic

g++ -fPIC -c DynamicMath.cpp

-fPIC 创建与地址无关的编译程序(pic,position independent code),是为了能够在多个应用程序间共享。

然后,生成动态库,此时要加链接器选项-shared

g++ -shared -o libdynmath.so DynamicMath.o

-shared指定生成动态链接库。

其实上面两个步骤可以合并为一个命令:

g++ -fPIC -shared -o libdynmath.so DynamicMath.cpp

4、使用动态库

编写使用动态库的测试代码:​​​​​​​

#include "../DynamicLibrary/DynamicMath.h"#include <iostream>using namespace std;int main(int argc, char* argv[]){    double a = 10;    double b = 2;    cout << "a + b = " << DynamicMath::add(a, b) << endl;    cout << "a - b = " << DynamicMath::sub(a, b) << endl;    cout << "a * b = " << DynamicMath::mul(a, b) << endl;    cout << "a / b = " << DynamicMath::div(a, b) << endl;    DynamicMath dyn;    dyn.print();    return 0;}

引用动态库编译成可执行文件(跟静态库方式一样):

g++ TestDynamicLibrary.cpp -L../DynamicLibrary -ldynmath

然后运行:./a.out,发现竟然报错了!!!

可能大家会猜测,是因为动态库跟测试程序不是一个目录,那我们验证下是否如此:

发现还是报错!!!那么,在执行的时候是如何定位共享库文件的呢?

    1) 当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统动态载入器(dynamic linker/loader)。

    2) 对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib 目录找到库文件后将其载入内存。

——————————

如何让系统能够找到它:

    ✪ 如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。

    ✪ 如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下:

        1. 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径

        2. 运行ldconfig ,该命令会重建/etc/ld.so.cache文件

我们将创建的动态库复制到/usr/lib下面,然后运行测试程序。

二、Windows下创建与使用动态库

1、创建动态库(.dll)

与Linux相比,在Windows系统下创建动态库要稍微麻烦一些。首先,需要一个DllMain函数做出初始化的入口(创建win32控制台程序时,勾选DLL类型会自动生成这个文件):​​​​​​​

// dllmain.cpp : Defines the entry point for the DLL application.#include "stdafx.h"BOOL APIENTRY DllMain( HMODULE hModule,                      DWORD  ul_reason_for_call,                      LPVOID lpReserved                    ){    switch (ul_reason_for_call)    {    case DLL_PROCESS_ATTACH:    case DLL_THREAD_ATTACH:    case DLL_THREAD_DETACH:    case DLL_PROCESS_DETACH:        break;    }    return TRUE;}

通常在导出函数的声明时需要有_declspec(dllexport)关键字:​​​​​​​

#pragma onceclass DynamicMath{public:    __declspec(dllexport) DynamicMath(void);    __declspec(dllexport) ~DynamicMath(void);    static __declspec(dllexport) double add(double a, double b);//加法    static __declspec(dllexport) double sub(double a, double b);//减法    static __declspec(dllexport) double mul(double a, double b);//乘法    static __declspec(dllexport) double div(double a, double b);//除法    __declspec(dllexport) void print();};

生成动态库需要设置工程属性,打开工程“属性面板”→”配置属性”→”常规”,配置类型选择动态库。

Build项目即可生成动态库。

2、使用动态库

创建win32控制台测试程序:​​​​​​​

#include "stdafx.h"#include "DynamicMath.h"#include <iostream>using namespace std;int _tmain(int argc, _TCHAR* argv[]){    double a = 10;    double b = 2;    cout << "a + b = " << DynamicMath::add(a, b) << endl;    cout << "a - b = " << DynamicMath::sub(a, b) << endl;    cout << "a * b = " << DynamicMath::mul(a, b) << endl;    cout << "a / b = " << DynamicMath::div(a, b) << endl;    DynamicMath dyn;    dyn.print();    system("pause");    return 0;}

▶ 方法一:

工程“属性面板”→“通用属性”→“框架和引用”→”添加引用”,将显示“添加引用”对话框。

“项目”选项卡列出了当前解决方案中的各个项目以及可以引用的所有库。在“项目”选项卡中,选择 DynamicLibrary。单击“确定”。

添加DynamicMath.h 头文件目录,必须修改包含目录路径。打开工程“属性面板”→”配置属性”→“C/C++”→” 常规”,在“附加包含目录”属性值中,键入DynamicMath.h 头文件所在目录的路径或浏览至该目录。

编译运行OK。

▶ 方法二:

“属性面板”→”配置属性”→“链接器”→”常规”,附加依赖库目录中输入,动态库所在目录;

“属性面板”→”配置属性”→“链接器”→”输入”,附加依赖库中输入动态库编译出来的DynamicLibrary.lib。

静态库与动态库深入研究——总结

结合之前的静态库与本篇动态库,总结出来二者的不同点在于代码被载入的时刻不同。

    ✪ 静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库,因此体积较大。

    ✪ 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在,因此代码体积较小。

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

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

相关文章

怎么打造WhatsApp Team?SaleSmartly(ss客服)告诉你

关键词&#xff1a;WhatsApp Team SaleSmartly&#xff08;ss客服&#xff09; 您是否正在寻找一种让您的团队能够在 WhatsApp协作消息传递的解决方案?拥有了 WhatsApp Team&#xff0c;不仅效率提升&#xff0c;还可以在智能聊天工具中比如SaleSmartly&#xff08;ss客服&…

51单片机——中断系统,小白讲解,相互学习

中断介绍 中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的&#xff0c;中断功能的存在&#xff0c;很大程度上提高了单片机处理外部或内部事件的能力。它也是单片机最重要的功能之一&#xff0c;是我们学些单片机必须要掌握的。 为了更容易的理解中断概念&…

算法思想 - 动态规划算法

动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中&#xff0c;可能会有许多可行解。每一个解都对应于一个值&#xff0c;我们希望找到具有最优值的解。动态规划算法与分治法类似&#xff0c;其基本思想也是将待求解问题分解成若干个子问题&#xff0c;先求解子问…

哈希表题目:判断路径是否相交

文章目录题目标题和出处难度题目描述要求示例数据范围解法一思路和算法代码复杂度分析解法二思路和算法代码复杂度分析题目 标题和出处 标题&#xff1a;判断路径是否相交 出处&#xff1a;1496. 判断路径是否相交 难度 3 级 题目描述 要求 给你一个字符串 path\texttt…

【软考系统架构设计师】2022下案例分析历年真题

【软考系统架构设计师】2022下案例分析历年真题 【软考系统架构设计师】2022下案例分析历年真题【软考系统架构设计师】2022下案例分析历年真题2022下案例分析历年真题第一题&#xff08;25分&#xff09;2022下案例分析历年真题第二题&#xff08;25分&#xff09;2022下案例分…

使用纹理(Textures)

当物体表面并非是纯色的时候&#xff0c;比如带波点&#xff0c;斑纹或者表面有刮痕或被裂纹等&#xff0c;这些效果该如何实现呢&#xff1f; 这里我们需要提到一个概念是贴图&#xff08;Maps&#xff09;。Maps是覆盖在游戏物体上的2D图片&#xff0c;用来设置表面的颜色、s…

大数据-学习实践-1相关Linux

大数据-学习实践-1相关Linux (大数据系列) 文章目录大数据-学习实践-1相关Linux1知识点2具体内容2.1安装、使用2.2高级命令2.2.1文件2.2.2日期2.2.3进程2.2.4三剑客 (grep、sed、awk)2.3高级配置2.3.1分配IP&#xff1a;静态IP设置2.3.2起名&#xff08;hostname&#xff09;&…

工程经验:残差连接对网络训练的巨大影响

文章目录1、没有使用残差连接的网络难以训练2、loss 不下降的原因3、使用了残差连接的网络可以高效训练1、没有使用残差连接的网络难以训练 经典的 SegNet 网络结构如下&#xff1a; 在使用上图所示的 SegNet 作为噪声预测网络训练扩散模型&#xff08;DDPM&#xff09;时&…

Elasticsearch汉字补全和智能纠错使用详解

1 使用ES实现的效果 汉字补全 拼写纠错

Python自动化测试【软件测试最全教程(附笔记、学习路线)】,看完即就业

最近看到很多粉丝在后台私信我&#xff0c;叫我做一期Python自动化测试的教程&#xff0c;其实关于这个问题&#xff0c;我也早就在着手准备了&#xff0c;我录制了一整套完整的Python自动化测试的教程&#xff0c;上传到网盘里了&#xff0c;大家有兴趣的可以去文末交流群免费…

[架构之路-107]-《软考-系统架构设计师》-0-系统分析师与系统架构设计师简介与官网介绍

官网链接&#xff1a;https://www.ruankao.org.cn/index/ind计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试简介计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;以下简称计算机软件资格考试&#xff09;是原中国计算机软件专业技术…

化学试剂Glutaric Acid-PEG-Glutaric Acid,GA-PEG-GA,戊二酸-聚乙二醇-戊二酸

一&#xff1a;产品描述 1、名称 英文&#xff1a;Glutaric Acid-PEG-Glutaric Acid&#xff0c;GA-PEG-GA 中文&#xff1a;戊二酸-聚乙二醇-戊二酸 2、CAS编号&#xff1a;N/A 3、所属分类&#xff1a;Carboxylic acid PEG 4、分子量&#xff1a;可定制&#xff0c; 戊…

如果网站的 Cookie 特别多特别大,会发生什么(一)

有没有想过&#xff0c;如果网站的 Cookie 特别多特别大&#xff0c;会发生什么情况&#xff1f; 不多说&#xff0c;马上来试验一下&#xff1a; for (i 0; i < 20; i) document.cookie i X.repeat(2000) 什么&#xff0c;网站居然报错了&#xff1f; 众所周知&am…

【Unity VR开发】结合VRTK4.0:自身移动(滑动)

语录&#xff1a; 依山傍水房树间&#xff0c;行也安然&#xff0c;住也安然&#xff1b; 一条耕牛半顷田&#xff0c;收也凭天&#xff0c;荒也凭天&#xff1b; 雨过天晴驾小船&#xff0c;鱼在一边&#xff0c;酒在一边&#xff1b; 夜晚妻子话灯前&#xff0c;今也谈谈…

考研复试机试 | C++

目录1.盛水最多的容器<11>题目代码&#xff1a;2.整数转罗马数字题目&#xff1a;代码&#xff1a;3. 清华大学机试题 abc题目题解4.清华大学机试题 反序数题目描述代码对称平方数题目代码&#xff1a;5. 杭电上机题 叠筐题目&#xff1a;代码pass&#xff1a;关于清华大…

Windows server——部署DNS服务(3)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.管理DNS服务 1.子域 案例 2. 委派 案例 1&#xff09;添加主机记录 …

替代AG9300|替代NCS8823|CS5260 Type-C转VGA视频转换方案

替代AG9300|替代NCS8823|CS5260 Type-C转VGA视频转换方案 CS5260是一款是一款实现USB TYPE-C到VGA视频转换的单片机解决方案转换器。CS5260支持USB Type-C显示端口交替模式&#xff0c;CS5260可以将视频和音频流从USB Type-C接口传输到VGA端口。在CS5260芯片中&#xff0c;显示…

01设计模式相关理论

设计模式git代码地址 设计模式分类 创建型模式 用于描述“怎样创建对象”&#xff0c;它的主要特点是“将对象的创建与使用分离”。GoF&#xff08;四人组&#xff09;书中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。结构型模式 用于描述如何将类或对象…

SQL注入Getshell的奇思妙想(下)

前言 由于笔者发现大量的hr面试官都喜欢从SQL注入开始询问&#xff0c;所以留心了一下关于SQL注入的问题的频率。结果非常amazing啊&#xff01;不出意外的是–os- shell名列榜首。 但是啊由于我们不能被面试官所引导&#xff0c;这样太被动啦&#xff01;我们应该引导hr问我们…

某财税集团:使用进步的技术,对业务降本提效

文 / OceanBase解决方案架构师 韩冰 该企业成立于 1999 年&#xff0c;是国内领先的财税信息化综合服务提供商&#xff0c;主要为税务机关提供税务系统开发与运维&#xff0c;为纳税企业和财税中介提供互联网财税综合服务。 经过多年发展&#xff0c;为了更好地支撑用户业务需…