11 【理解动静态库】

前言:我们写的方法如何给别人用

当我们写了一些通用方法,想给别人使用时,通常有两种选择:

  • 方法一:直接提供源码(.h + .c)

    • 将头文件和源文件一并发给对方,对方可以直接编译使用。但问题是:别人能直接看到你的代码实现,劳动成果暴露无遗!
  • 方法二:提供头文件 + 打包后的库文件(.h + 库)

    • 将源文件编译并打包成库文件,再连同头文件一并提供。这样:别人只能使用你提供的接口,而看不到实现细节!

补充说明:

  • 头文件(.h)是必须公开的,它就像“说明书”,告诉别人该怎么使用你的函数接口;
  • 而源文件(.c)中真正的函数实现,则可以通过打包成静态库或动态库来进行“封装”。

1 静态链接

1.1 什么是静态库?

静态库就是 .a 文件(在 Linux 下),例如 libmath.a,其本质是多个 .o 文件(目标文件)的打包集合。

当我们用 main.c 编写自己的主程序时,编译器会:

  • 把 main.c 编译为 main.o
  • 然后把别人提供的 libXXX.a(静态库)一起链接
  • 最终生成可执行程序

这样就不再需要源码,也能正常使用库中方法,实现了功能复用与源码保护的双赢。

1.2 静态库的原理

原理:把我们写的方法相关 .c 源文件先编译为 .o,然后通过工具打包成 .a 文件。

命令行操作:

gcc -c add.c        # 将源文件编译为目标文件 add.o
gcc -c sub.c        # 将源文件编译为目标文件 sbu.o

ar -rc libmath.a add.o sub.o   # 将多个.o文件打包成静态库libmath.a
  • ar 是用于操作静态库的工具
  • 其中 -rc 表示:r(replace)替换已有文件、c(create)创建新文件

1.3 静态库制作和公开

在这里插入图片描述
可以完成静态库的制作,然后可以公开出去,变成一个lib文件夹给用户

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

1.4 库使用及路径问题

在这里插入图片描述

如果文件都在当前路径,也可以:

在这里插入图片描述
前面两个路径不能省略!!!(它只会去默认路径寻找,不会去当前路径寻找!!!)

1.5 errno的理解

在这里插入图片描述

在这里插入图片描述

2 动态链接

2.1 动态库的原理和命令

  动态库的原理和静态库一样,因为最后都要链接,所以都是先把-c变成-o,然后再用命令打包起来。

和静态库的区别:

  1. gcc编译多了一个选项 -fPIC :gcc -fPIC -c mylog.c生成.o文件
  2. gcc -shared -o libmymethod.so *.o把所有的.o文件打包成.so文件,前面多了一个-shared

2.2 尝试动静态库分离

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

dy-lib=libmymethod.so
static-lib=libmymath.a

.PYONY:all     // 一次生成两个可执行文件
all: $(dy-lib) $(static-lib)

$(static-lib):mymath.o   // 打包所有,点o文件,形成静态库
	ar -rc $@ $^         // ar -rc 是静态库打包特有的
mymath.o:mymath.c
	gcc -c $^        // 不写$@,默认生成,点o文件

$(dy-lib):mylog.o myprint.o   // 打包所有,点o文件,形成动态库
	gcc -shared -o $@ $^      // -shared是打包动态库特有的
mylog.o:mylog.c
	gcc -fPIC -c $^    // -fPIC 是动态库形成点o文件特头的
myprint.o:myprint.c
	gcc -fPIC -c $^

.PYONY:clean
clean:
	rm -rf *.o *.a *.so mylib

.PYONY:output
output:
	mkdir -p mylib/include
	mkdir -p mylib/lib
	cp *.h mylib/include
	cp *.a mylib/lib
	cp *.so mylib/lib

在这里插入图片描述

make; make output后,动态库就形成了。

在这里插入图片描述

  gcc main.c -I mylib/include/ -L mylib/lib/ -l mymethod可以形成可执行程序 a.out文件,但是这个可执行不能直接运行!!!

在这里插入图片描述
在这里插入图片描述
问题:为什么明明形成了a.out 却还是出现这种情况呢?
  我曾经告诉过编译器动态库在哪里,编译器也帮我生成了可执行程序,但是当形成可执行程序之后,就和编译器一无关了,可执行程序运行不了,是因为我们没用告诉系统(加载器)动态库在哪。

2.3 解决加载找不到动态库的方法

方法一:动态库直接拷贝到系统默认的库路径/usr/lib

在这里插入图片描述

方法二:在系统的默认库路径/usr/lib 建立软连接
sudo ln -s /home/hyq/HYQ/hyq9/mylib/lib/libmymethod.so /lib/libmymethod.so
在这里插入图片描述
在这里插入图片描述

方法三:将自己库所在的路径,添加到环境变量LD_LIBRARY_PATH(搜索用户自定义库路径)中
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/hyq/HYQ/hyq9/mylib/lib

在这里插入图片描述
缺点:关闭shell之后就会失效!!!

其实还有方法四:/etc/ld.so.conf.d 建立自己的动态库路径的配置文件,然后ldconfig一下(没懂意思,算了,不写了)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值