ARM_C高级学习笔记(九)函数库

函数库

什么是函数库?

  1. 函数库就是一些事先写好的函数的集合,给别人复用。
  2. 函数是模块化的,因此可以被复用。我们写好了一个函数,可以被反复使用。也可以A写好了一个函数然后共享出来,当B有相同的需求时就不需自己写直接用A写好的这个函数即可。

函数库的提供形式:动态链接库与静态链接库

  1. 早期的函数共享都是以源代码的形式进行的。这种方式共享是最彻底的(后来这种源码共享的方向就形成了我们现在的开源社区)。但是这种方式有它的缺点,缺点就是无法以商业化形式来发布函数库。
  2. 商业公司需要将自己的有用的函数库共享给被人(当然是付费的),但是又不能给客户源代码。这时候的解决方案就是以库(主要有2种:静态库和动态库)的形式来提供。
  3. 比较早出现的是静态链接库。静态库其实就是商业公司将自己的函数库源代码经过只编译不连接形成.o的目标文件,然后用ar工具将.o文件归档成.a的归档文件(.a的归档文件又叫静态链接库文件)。商业公司通过发布.a库文件和.h头文件来提供静态库给客户使用;客户拿到.a和.h文件后,通过.h头文件得知库中的库函数的原型,然后在自己的.c文件中直接调用这些库文件,在连接的时候链接器会去.a文件中拿出被调用的那个函数的编译后的.o二进制代码段链接进去形成最终的可执行程序。
  4. 动态链接库比静态链接库出现的晚一些,效率更高一些,是改进型的。现在我们一般都是使用动态库。静态库在用户链接自己的可执行程序时就已经把调用的库中的函数的代码段链接进最终可执行程序中了,这样好处是可以执行,坏处是太占地方了。尤其是有多个应用程序都使用了这个库函数时,实际上在多个应用程序最后生成的可执行程序中都各自有一份这个库函数的代码段。当这些应用程序同时在内存中运行时,实际上在内存中有多个这个库函数的代码段,这完全重复了。而动态链接库本身不将库函数的代码段链接入可执行程序,只是做个标记。然后当应用程序在内存中执行时,运行时环境发现它调用了一个动态库中的库函数时,会去加载这个动态库到内存中,然后以后不管有多少个应用程序去调用这个库中的函数都会跳转到第一次加载的地方去执行(不会重复加载)。

函数库中库函数的使用

  1. gcc中编译链接程序默认是使用动态库的,要想静态链接需要显式用-static来强制静态链接。
  2. 库函数的使用需要注意3点:第一,包含相应的头文件;第二,调用库函数时注意函数原型;第三,有些库函数链接时需要额外用-lxxx来指定链接;第四,如果是动态库,要注意-L指定动态库的地址。

自己制作静态链接库并使用

  1. 第一步:自己制作静态链接库
  • 首先使用gcc -c只编译不连接,生成.o文件;然后使用ar工具进行打包成.a归档文件
//使用makefile完成以上工作
all:
	gcc aston.c -o aston.o -c
	ar -rc libaston.a aston.o
  • 库名不能随便乱起,一般是lib+库名称,后缀名是.a表示是一个归档文件
  • 注意:制作出来了静态库之后,发布时需要发布.a文件和.h文件。
  1. 第二步:使用静态链接库
  • gcc test.c 报错
/tmp/ccHcm1R9.o: In function `main':
test.c:(.text+0x5): undefined reference to `func1'
test.c:(.text+0xa): undefined reference to `func2'
collect2: error: ld returned 1 exit status

  • gcc test.c -o test -laston 报错
/usr/bin/ld: cannot find -laston
collect2: error: ld returned 1 exit status
  • 链接时加-laston(-lxxx),就是告诉链接器到libaston(libxxx)中去查找用到的函数。
  • gcc test.c -o test -laston -L.编译通过,运行也正常
    • -L.(-Lxxx):就是告诉链接器在哪里去找到laston

自己制作动态链接库并使用

  1. 动态链接库的后缀名是.so(对应windows系统中的dll),静态库的扩展名是.a
  2. 第一步:创建一个动态链接库。
all:
	gcc aston.c -o aston.o -c -fPIC
	gcc -o libaston.so aston.o -shared 
  • -fPIC是位置无关码,-shared是按照共享库的方式来链接。
  • 注意:做库的人给用库的人发布库时,发布libxxx.so和xxx.h即可。
  1. 第二步:使用自己创建的共享库。
  • 第一步,编译方法:gcc test.c -o test报错
/tmp/ccbKiNBL.o: In function `main':
test.c:(.text+0x5): undefined reference to `func1'
test.c:(.text+0xa): undefined reference to `func2'
collect2: error: ld returned 1 exit status
  • 第二步,编译方法:gcc test.c -o test -laston报错
/usr/bin/ld: cannot find -laston
collect2: error: ld returned 1 exit status
  • 第三步,编译方法:gcc test.c -o test -laston -L.编译通过
    • 但是运行报错
./test: error while loading shared libraries: libaston.so: cannot open shared object file: No such file or directory
  • 错误原因:动态链接库运行时需要被加载(运行时环境在执行test程序的时候发现他动态链接了libaston.so,于是乎会去固定目录尝试加载libaston.so,如果加载失败则会打印以上错误信息。)
  • 解决方法一:将libaston.so放到固定目录下就可以了,这个固定目录一般是/usr/lib目录。
cp libaston.so /usr/lib
  • 解决方法二:使用环境变量LD_LIBRARY_PATH。操作系统在加载固定目录/usr/lib之前,会先去LD_LIBRARY_PATH这个环境变量所指定的目录下去寻找,如果找到就不用去/usr/lib下面找了,如果没找到再去/usr/lib下面找。所以解决方案就是将libaston.so所在的目录导出到环境变量LD_LIBRARY_PATH中即可。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mnt/hgfs/win10share/ARM_C/4.6/dynamicfunclib/testlib
  1. 在ubuntu中还有个解决方案三,用ldconfig(仅ubuntu中有,所以不推荐使用)
  • ldd命令:作用是可以在一个使用了共享库的程序执行之前解析出这个程序使用了哪些共享库,并且查看这些共享库是否能被找到,能被解析(决定这个程序是否能正确执行)。
发布了21 篇原创文章 · 获赞 6 · 访问量 410

猜你喜欢

转载自blog.csdn.net/weixin_44112805/article/details/105258836