静态库与动态库混合链接

准备

在linux下,终端完成c/c++的编译运行,如果使用到静态库与动态库,那么如何链接?这里以一个例子来完成讲述。假如当前位于test目录,且有a.h、a.c、b.h、 b.c,以及调用a、b中方法的main.c。
在这里插入图片描述
每个文件的内容如下

//a.c文件内容如下
#include<stdio.h>
void a(){
printf("The first file a\n");
}
//a.h的内容如下
#ifndef A_H
#define A_H
extern void a();
//b.c文件的内容如下
#include<stdio.h>
void b(){
printf("The second file b\n");
}
//b.h的内容如下
#ifndef B_H
#define B_H
extern void b();
//最后一个main.c是我们的调用文件
int main(int argc,char *argv[]){
	a();
	b();
return 0;
}

使用静态库

首先我们先要将源代码制作成静态文件,静态文件以.a形式结尾,如用的命令ar,例如本例:

gcc -g -c a.c -o a.o //生成.o文件
ar -rc liba.a a.o //形成静态库
gcc -g -c b.c -o b.o
ar -rc libb.a b.o

结果如图所示:
在这里插入图片描述
最后一步就是main.c对静态库的调用

gcc -g main.c -o main a.a b.a  //对静态库的调用
./main   //运行生成的可执行文件main

结果如图:
在这里插入图片描述

使用动态库

采用动态库链接的方式,首先需要得到.so结尾的动态链接库,还是以文章开头的文件为例

gcc -fpic -shared a.c -o liba.so  //a.c生成动态库liba.c ,动态库文件一般以lib + 文件名+.so组成
gcc -fpic -shared b.c -o libb.so  //同上

在这里插入图片描述
然后一样的通过我们的maic.c对动态库进行链接

gcc main.c -L. -l a b -o main  //根据命令规则 lib+文件名+.so,所以这里只需要指定文件名,-L指定库文件目录,.代表当前目录,-l指定库文件名。

注意:这里我们的动态链接可能会得到error while loading shared libraries: liba.so: cannot open shared object file: No such file or directory的错误。
解决办法如下:
root用户下,vim /etc/ld.so.conf ,加入我们自定义库文件的目录,我这里是/root/test,如图所示
在这里插入图片描述
最后得到main文件成功运行

使用动态库与静态库的混合链接

这里我们让a生成静态文件liba.a,b生成动态文件libb.so,这两个文件的生成和前面一样,我们这里说如何在main.c中同时对两种库链接

gcc main.c -L. -Wl,-Bstatic -la -WI,-Bdynamic -lb -o main

注意

  • 一定要注意大小写

  • -Wl,-Bstatic:禁用动态库

  • -Wl, -Bdynamic :禁用静态库

  • 如果你的两套参数和我的相反,一定记得最后再加一个一Wl,-Bdynamic,因为默认是采用的动态库,如果禁止了,后面就没法搞了。

静态库与动态库的区别

两种链接库的使用我们已经会了,那么这两种库有什么区别呢?他们分别有什么优缺点?
静态库
在源程序链接阶段,链接器将从库文件取得所需代码,复制到生成的可执行文件中在编译阶段完成我们代码的链接,会导致生成的执行文件变大,使用的到的地方都需要加载一份到内存,不方便升级,但是装载速度快
动态库
动态库在链接阶段没有被复制到程序中,而是在程序运行时由系统动态加载到内存中供程序调用。动态库可以实现进程之间资源共享,仅需要装载到内存一次,升级简单。但是会减缓装载的速度,增加程序的依赖性。

总结

好了,我们本文的例子就写到这里了,细心的同学可能发现,在这个例子中,如果我们读某一个文件进行稍微的改动就会导致整个工程挂钩的文件都需要进行重新编译,那有没有什么办法避免这样的麻烦呢?当然有,那就是make 与Makefile,使用make可以避免很多麻烦,他可以自行更改与更新挂钩的文件,下一篇文章我们就来聊聊make与Makefile

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章