程序库的制作和使用

库的概念

  • 库是二进制文件,包含的代码可被调用
  • 标准C库、数学库、线程库……
  • 库有源码,可下载后编译;也可以直接安装二进制包
  • 系统默认库的位置/lib /usr/lib
  • 库是事先编译好的,可以复用的代码
  • win和Linux库不兼容
  • LInux下包含静态库和共享库

静态库

优缺点

  • 编译(链接)时把静态库中的相关代码复制到可执行文件中
    • 程序 中以包含代码,运行是不再需要静态库
    • 程序运行时无须加载库,运行速度更快
    • 占用更多磁盘和内存空间
    • 静态库升级后,程序需要重新编译链接

静态库的创建

  • 确定库中函数的功能、接口
  • 编写库源码hello.c
#include <stdio.h>

void hello(void)
{
    
    
	puts("量子孤岛");
	return;
}
  • 编译生成目标文件
$ gcc -c hello.c -Wall
  • 创建静态库hello
$ ar crs libhello.a hello.o

注意:静态库名称lib**.a是固定格式,**是库名

  • 查看库中符号
$ nm libhello.a 

>>>>>
hello.o:
           
0000000000000000 T hello
                 U puts

链接静态库

  • 编写应用程序
#include <stdio.h>

void hello(void);

int main()
{
    
    
	hello();
	return 0;
}
  • 编译test.c并链接静态库libhello.a
$ gcc -o test test.c -L. -lhello

-l:指定链接库的名称
-L:指定链接库的路径

编译器默认链接C库

删除库程序依然能运行,因为静态库代码会被复制到程序中。

共享库

特点

  • 编译(链接)时仅记录用到哪个共享库中的哪个符号,不复制共享库中相关代码
    • 程序不包含库中代码,尺寸小
    • 多个程序可共享同一个库
    • 程序运行时才会加载库
    • 库升级方便,无须重新编译程序

共享库的创建

1. 确定库中函数的功能、接口
2. 编写库源码hello.c bye.c

#include <stdio.h>
void bye(void)
{
    
    
	puts("bye!");
}

3. 编译生成目标文件

$ gcc -c -fPIC hello.c bye.c -Wall

-fPIC:生成位置无关代码

4. 创建共享库common

$ gcc -shared -o libcommon.so.1 hello.o bye.o

说明:
.so:表示共享库文件,.数字——表示库的版本
命名规则:lib<库名>.so.x

5. 为共享库文件创建链接文件

$ ln -s libcommon.so.1 libcommon.so

目的就是编译器在编译时能找到共享库
版本号的好处就是一个库可以有不同的版本,.so指向哪一个文件就调用哪一个库

为库提供头文件,更加规范一些

$ gcc -o test test.c -L. -lcommon

这里和静态库是一样的,怎么区分呢?
gcc会优先链接共享库,如果不存在则链接静态库,如果静态库也没有,就会报错。
加上-static选项,即为直接链接静态库

出现:

./test: error while loading shared libraries: libcommon.so: cannot open shared object file: No such file or directory

因为当前目录没有在系统的搜索目录中

执行:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.

如何找到共享库?

  1. 把库拷贝到/usr/lib和/lib目录下
  2. 在LD_LIBRARY_PATH环境变量中添加库所在路径,缺点是重开shell失效
  3. sudo vim /etc/ld.so.conf.d/*conf文件,sudo ldconfig刷新
    就是添加新文件,随便起名字,然后把库的目录添加进去
    /home/linux/io/lib/share

然后刷新

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/fly_wt/article/details/109963548