Linux平台下自创c函数库及库的命名约定

2021/10/2 7:12:19

本文主要是介绍Linux平台下自创c函数库及库的命名约定,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 如下所示,一段的简单到不能再简的程序:

Linux平台下自创c函数库及库的命名约定

我们可以重新查看这个小程序,在这个程序中并没有定义”printf”的函数实现,且在预编译中包含进的”stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实现”printf”函数的呢?最后的答案是:系统把这些函数实现都被做到名为libc.so.6的库文件中去了,在没有特别指定时,Gcc会到系统默认的搜索路径”/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去,这样就能实现函数”printf”了,而这也就是链接的作用。

怎么能看得到自己的程序main.out是否真链接到libc.so.6库函数中去呢?linux命令“ldd”就是干这个的。(上图绿线上就是)

Linux平台下自创c函数库及库的命名约定

 在linux中,大量的C库函数被封装在动态链接库“libc.so.6”中,你只需用声明其头文件,调用其C函数接口即可。通常,我们把操作系统调用接口称之为:系统API。标准C库处理调用操作系统API,处理与操作系统层打交道的复杂细节,几乎把所有的苦活累活都替你干了,完了交了一把钥匙给你。

  其实,库是已经写好的、成熟的、可复用的代码。每个程序都需要依赖很多底层库,不可能每个人的代码从零开始编写,因此,库的存在具有非常重要的意义,就像C/C++库一样,不管是windows还是linux,都必不可少。

  所以,不要把库看得过于高深,我们的开发的应用中经常有一些公共代码是需要反复使用的,就可以把这些代码编译为库文件,方便使用。

  库有静态库和动态库之分,我们可以很简单地制作出来。前提是,我们得知道一个简易C代码的基本编译方法与步骤,就可以了。

Linux平台下自创c函数库及库的命名约定

代码:main.c
----------------------------------------------
#include <stdio.h>
extern void my_lib_func_001();
extern void my_lib_func_002();

int main(void)
{
my_lib_func_001();
my_lib_func_002();
}

代码:f1.c
---------------------------------------------
#include <stdio.h>
void my_lib_func_001()
{
    printf("This is my my_lib_func_001 ... \n");
}

代码:f2.c
--------------------------------------------
#include <stdio.h>
void my_lib_func_002()
{
    printf("This is my my_lib_func_002 ... \n");
}

创建静态链接库

我们想把f1.c中的“my_lib_func_001”和f2.c中的函数"my_lib_func_002",制作一个静态库,仅需两步。。

(1)把f1.c和f2.c制作成二进制文件,生成:f1.o,f2.o

gcc -c f1.c f2.c

(2)生成静态库

ar -crv libmyStaticLib.a f1.o f2.o

"libmyStaticLib.a"生成静态函数库的名字。

(3)使用静态库

gcc main.c f1.c f2.c -o main.out

如果不使用静态库,我们可以像上面这样一行,来简单地编译输出main.out程序:

使用静态库方式,输出mainStatic.out程序,我们的编译命令如下:

gcc -o mainStatic.out main.c -static -L . -l myStaticLib

与是我们的新程序“mainStatic.out”也成功的生成了。

运行mainStatic.out :

$ ./mainStatic.out

This is my my_lib_func_001 ...

This is my my_lib_func_002 ...

说明静态链接库的编译是正确的,程序工作正常。

两个问题

这里有两个问題,在第(2)步,为什么要用"libmyStaticLib.a"作为静态函数库的名字,难道不可以用“myStaticLib.a”或者“a_sampleStaic.a”吗?

还有,既然第(2)步编译出来的静态函数库是"libmyStaticLib.a",第三步命令行中的“myStaticLib”从何而来?

好吧,我承认我也这样做过。但是编译器提示错误:“/usr/bin/ld: 找不到 -la_sampleStatic.a”

Linux平台下自创c函数库及库的命名约定

Linux库的命名约定

Linux平台上,库的命名一般是以".a"为后缀,动态库以".so"为后缀。

Linux平台上,库的命名必须如 libname.so.x.y.z格式。最前面使用前缀”lib”,中间是库的名字和后缀”.so”,最后三个数字是版本号。x是主版本号(Major Version Number),y是次版本号(Minor Version Number),z是发布版本号(Release Version Number)。
主版本号(不兼容):重大升级,不同主版本的库之间的库是不兼容的。所以如果要保证向后兼容就不能删除旧的动态库的版本。
次版本号(向下兼容): 增量升级,增加一些新的接口但保留原有接口。高次版本号的库向后兼容低次版本号的库。
发布版本号(相互兼容):库的一些诸如错误修改、性能改进等,不添加新接口,也不更改接口。主版本号和此版本号相同的前提下,不同发布版本之间完全兼容。

所以,上面的静态函数的名字"libmyStaticLib.a"不是乱起的,gcc严格遵循这个命名约定,库不以lib开头,就无法用gcc编译,而实际编译中,又要去掉lib这三个字符。编译命令“gcc -o mainStatic.out main.c -static -L . -l myStaticLib”中神奇的“myStaticLib”就是这么来的。(当然,人个测试小程序,就不要版本号xy了)

同理,下面在动态链接库创建过程中,也严格遵循这个命名约定。不仅如此,编译静态库时,还要去掉".a"后缀,编译动态库时,还要去掉".so"后缀。

创建动态链接库

(1)生成动态库

gcc -fPIC -shared -o libmyDynamicLib.so f1.c f2.c

GCC 生成动态链接库 .so 文件 (-shared 和 -fPIC 选项)

fPIC f后面跟一些编译选项,PIC是其中一种,表示生成位置无关代码(Position Independent Code),share 表示调用动态库。

(2)链接生成目标文件

gcc -o mainDynamic.out main.c -L . -l myDynamicLib

(3)拷贝动态库文件libmyDynamicLib.so

sudo cp libmyDynamicLib.so /lib/x86_64-linux-gnu/

拷贝动态库文件libmyDynamicLib.so到“/lib/x86_64-linux-gnu/“下面。

测试运行mainDynamic.out :

$ ./mainDynamic.out

This is my my_lib_func_001 ...

This is my my_lib_func_002 ...

说明动态链接的编译是正确的,程序工作正常。



这篇关于Linux平台下自创c函数库及库的命名约定的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程