C语言-模块化-Clion(静态库,动态库)使用

什么是模块化编程

模块化编程就是我们一个复杂的项目分成很多模块,比如一个单片机项目,就可能分为:主函数模块,液晶显示和数码管显示模块,时间延时模块,温度传感器模块等。而一个程序工程包含多个源文件(.c 文件和 .h 文件),每个 .c 文件可以被称为一个模块,每一个模块都有其各自的功能,而每一个.h文件则是声明该模块,相当于功能说明书 模块化编程在嵌入式中是必须要掌握的技能。

模块化编程的好处

开发C程序时,当代码量较大功能较复杂时,单一文件程序会使得文件非常巨大,代码量非常大,成千上万行的代码在一个文件中不便于修改和维护,因此需要将不同的功能模块放在不同的文件中。

并且在团队合作开发的时候,需要模块化开发。每个人负责一部分功能的开发,而你所负责的模块,你需要将你负责的模块功能写好,封装好,之后形成一个.c与.h ,然后交付给项目组长,组长则负责整体框架(main)的编写与各个模块的组合调试,最后各个模块的组合,形成了整个工程。由此可见,模块化可以有效的提高团队开发的分工协作效率。对于整个项目开发有着很大的好处

模块化开发过程如下

  1. 创建.c文件
  2. 在.c文件内定义需要的函数和变量
  3. 创建.h文件,文件名要与.c文件一致
  4. 在.h文件中声明需要让调用方知道的函数和变量
  5. 在调用方文件中包含.h文件,直接调用.h文件中声明的内容即可

注意事项:

  • .h头文件格式一定要按照下面这格式进行
#ifndef DEMO1_CALCULATE_H  // 避免多个文件重复导入
#define DEMO1_CALCULATE_H  // 定义一个预处理宏定义

//extern   声明代码

#endif //DEMO1_CALCULATE_H   表示条件命令的结束
  • 导入.h文件的时候不能使用<> 而是使用" " 因为<>方式只会到系统的专门目录找,而这里没有我们定义的模块 ,而" "方式编译器会先到当前的工程项目所在目录下找,找不到再到系统专门目录下找

  • 定义的x.c和x.h要在同一个目录下不然引入x.h的时候找不到.c源码

  • .h文件 不能定义具体实现 ,只能进行声明, 而具体实现都需要在.c文件中定义

  • 函数声明时,extern可有可无,但是变量的声明必须要有,否则编译时不能识别。. (建议都写上)

  • 不想让外界知道的信息,就不应该出现在.h头文件里,而想让外部调用的函数或变量,则一定要在头文件中声明

  • 头文件(.h)命名应与源文件(.c)一致,便于清晰的查看各个头文件

  • 模块内不想被外部引用的函数和全局变量需在.c文件头以static关键字声明, 这样这些函数和变量只会在当前.c文件中起到作用,一来可以避免函数名的重复;二来可以保护内部的实现数据,防止被破坏 ,比如: static void lEDOpen();

  • 模块中想要被其他文件访问的变量,一定要是全局变量,并且在.h中声明

  • 要尽量减少全局变量的使用,因为全局变量的生命周期是从程序的开始到程序的结束的,这意味着你在其他源文件中调用这个变量时,可能会产生同名变量以及变量数值错误等问题, 这个是非常不好把控的,程序一旦庞大起来,这就是灾难

模块化演示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

然后我们在需要调用的地方,将头文件导进来就行了,之后就能使用头文件中声明的内容了
在这里插入图片描述
在上面的案例中我们只是在main.c文件中应用了模块,那么模块和模块之间能相互引用吗? 答案是可以的,直接导入就行了

在这里插入图片描述

代码库

代码编译过程

在这里插入图片描述

静态库

静态库,顾名思义,它是静态的,也就是说它不会被动态编译,它只会静态编译,节省了编译时间,提高了编译速度。同一份静态库,可以被多个程序进行编译,也就实现了代码的复用共享。

在这里插入图片描述
静态库的后缀一般有2种.a(linux) , .lib(windows) ,但是在windows下MinGW编译的静态库也是.a的所以如果使用MinGw进行编译代码的话.a文件能通用的

静态库命名规则: 这类库的名字一般是libxxx.a;或者 libxxx.lib; 而xxx是库的名称

动态库

动态库,就是程序应用启动的时候,动态加载的,因为它一般是在系统运行的时候就已经运行的动态库,因此其它应用可以直接使用它,并且同一个动态库可以被多个应用共享使用,在系统中对于一个动态库只会存在一份,这大大节省了内存空间,大大提升了系统的性能。
在这里插入图片描述
动态库的后缀一般也是2种 展名分别为:.so( linux )或者 .dll(windows)

动态库命名规则: 这类库的名字一般是libxxx.so 或者libxxx.dll 而xxx是库的名称

Clion库的使用

CMakeLists.txt文件使用

C语言-Cmake-CMakeLists.txt教程 可以参考这篇文章

静态库

创建静态库

先写好c代码,在demo中调试没问题了,那么我们就可以将相关的代码copy到静态库中进行打包了,下面就创建一个静态库
在这里插入图片描述

然后随便创建几个.c和.h文件 如下:

在这里插入图片描述

然后可以参考C语言-Cmake-CMakeLists.txt教程 ->打包静态或动态库CMakeLists.txt(通用) 这篇文章进行配置CMakeLists.txt ,之后打包效果如下:

在这里插入图片描述

注意: 打包后会自动在项目名称前加lib ,所以在创建的时候无效前缀加lib

使用静态库

然后我们将打包好的libtool.a 和头文件目录tool 都拷贝到需要的地方,然后可以参考C语言-Cmake-CMakeLists.txt教程-> 项目编译CMakeLists.txt(静态动态库通用)这篇文章, 进行配置CMakeLists.txt, 项目编译之后在调用的地方使用#include "头文件"就行
在这里插入图片描述

如果发现编译错误那么,记得刷新Clion-CMake的缓存

动态库

创建动态库

先写好c代码,在demo中调试没问题了,那么我们就可以将相关的代码copy到动态库中进行打包了,下面就创建一个动态库
在这里插入图片描述

然后随便创建几个.c和.h文件 如下:
在这里插入图片描述
然后可以参考C语言-Cmake-CMakeLists.txt教程 ->打包静态或动态库CMakeLists.txt(通用) 这篇文章进行配置CMakeLists.txt ,之后打包效果如下:

在这里插入图片描述

使用动态库

使用MinGW动态打包后就会出现两个文件.dll .dll.a 我们只需要.dll 就行,然后我们将打包好的libtool1.dll 和头文件目录tool1 都拷贝到需要的地方,然后可以参考C语言-Cmake-CMakeLists.txt教程-> 项目编译CMakeLists.txt(静态动态库通用)这篇文章, 进行配置CMakeLists.txt, 项目编译之后在调用的地方使用#include "头文件"就行
在这里插入图片描述
上面可以看出来运行报错了,这是因为默认exe程序会去当前目录下找dll文件如果没有找到那么就会去环境变量里找,都没有找到那么就报错了具体解决办法,可以参考这篇文章C语言-Cmake-CMakeLists.txt教程 动态库导入无效,报错问题

静态库和动态库混合使用

可以参考这篇文章C语言-Cmake-CMakeLists.txt教程 打包静态或动态库CMakeLists.txt(通用)

查看动态库或者静态库

查看动态库定义的函数或变量 readelf -c xxx.a

查看动态库定义的函数或变量 readelf -A xxx.so

查看库里所有文件列表: ar -t xxx.a

查找静态库里指定的函数或变量 nm -o xxx.a | grep "yyy"

查找动态库里指定的函数或变量 nm -o xxx.so | grep "yyy"

nm 常见的符号类型:

A 该符号的值在今后的链接中将不再改变;
B 该符号放在BSS段中,通常是那些未初始化的全局变量;
D 该符号放在普通的数据段中,通常是那些已经初始化的全局变量;
T 该符号放在代码段中,通常是那些全局非静态函数;
U 该符号未定义过,需要自其他对象文件中链接进来;
W 未明确指定的弱链接符号;同链接的其他对象文件中有它的定义就用上,否则就用一个系统特别指定的默认值。

小技巧

常用的工具类我们可以使用静态库, 频繁升级的部分我们可以使用动态库

  • 静态库的好处就是打包后的exe不需要依赖任何文件就能运行,只是exe文件会比较大
  • 动态库的好处就是打包后的exe文件小,升级只需替换对应的dll文件就行,坏处就是dll找不到或者丢失程序就没法运行了

注意: 动态库代码和项目代码是分离的,如果更新的版本与原来的版本不兼容的话,使用动态库的新版本加载后有可能会出问题导致项目崩溃等情况。

主要还是看项目升级频繁吗?

  • 如果只是单存的开发一个自己使用的工具或者以后不打算升级了,那么使用静态库是非常不错的选择, 因为移植性强,在哪里都能直接用无须安装和配置,双击就运行了
  • 如果是商用项目经常需要升级扩展,那么不用想动态库就是不二的选择,升级和扩展只需要添加或者更换部分的dll就行
  • 当然很多时候我们静态和动态可以混合使用, 静态库主要用于工具文件或者项目核心功能, 动态库用于项目的变化频繁的功能, (静态库和动态库都有相同的文件,内部方法也相同那么优先静态库)

在这里插入图片描述

点赞 -收藏-关注-便于以后复习和收到最新内容
有其他问题在评论区讨论-或者私信我-收到会在第一时间回复
感谢,配合,希望我的努力对你有帮助^_^

免责声明:本文部分素材来源于网络,版权归原创者所有,如存在文章/图片/音视频等使用不当的情况,请随时私信联系我。
根据引用的内容,如果你使用的是libmspack来编译安装,可能会导致应用程序无法正常启动并出现错误代码0xc000007b。这是由于程序依赖的文件没有正确配置或者缺失所导致的。你可以尝试重新编译安装libmspack,并确保配置正确的依赖项。 另外,根据引用的内容,如果你是在Ubuntu 18.04.1系统下使用vmware,你可以直接安装和启动,而不需要手动编译安装驱动。这也是一个可以避免出现启动错误的方法。 此外,根据引用的内容,虚拟化后,GuestOS不能运行在最高权限级别下执行敏感指令,而是由虚拟机管理器(VMM)处理执行。这可能会对一些需要在Ring 0上执行的指令产生影响,也可能导致应用程序无法正常启动。 为了解决问题,你可以尝试以下步骤: 1. 确认你的程序依赖的文件是否正确配置并且没有缺失。 2. 如果你使用的是libmspack,可以尝试重新编译安装,并确保依赖项的正确配置。 3. 如果你使用的是Ubuntu 18.04.1系统下的vmware,确保已经正确安装和启动,不需要手动编译安装驱动。 4. 如果问题仍然存在,可能是由于虚拟化造成的限制。你可以尝试在物理机上运行程序,或者查找其他虚拟化解决方案以解决该问题。 请根据你的具体情况尝试上述步骤,并确保你的程序和环境的配置正确。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [VMware 逃逸基础知识](https://blog.csdn.net/qq_45323960/article/details/131275005)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡安民

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值