动态库和静态库
静态库:仅仅是一组目标文件的集合,简单的包装到一起,起到一个文件夹的作用,比如你的main.c分别用到h1.c h2.c h3.c里的函数,自然地h1.c h2.c h3.c各自都可以编译为对应的.o文件,虽然这里只有三个,但实际情况下可以有很多,那么你在编译main.c这个文件时是不是需要这样写gcc main.c h1.o h2.o h3.o -o main,如果这样的.o文件太多,你就会崩溃,这个时候如果能将这些.o文件打包在一起,用起来就方便多了。比如将h1.o h2.o h3.o打包为libhelp.a静态库,在使用的时候只需要gcc main.c -lhelp,通过这种方式,能简化一些,而且在链接过程中,已将库中的代码链接到可执行文件main中,之后main的运行就不再需要libhelp.a这个文件了。
动态库:和静态库不一样,使用动态库的程序,仅在运行时才去链接动态库中的代码,且程序共享动态库的代码,每个可执行程序和动态库之间保存一份函数地址表,运行时查表去执行相应代码,所以动态库在程序运行时必须在场。
自己生成动态库和静态库
生成静态库:
// static_help.h
#ifndef __STATIC_HELP_H_
#define __STATIC_HELP_H_
int static_help();
#endif
// static_help.c
#include <stdio.h>
#include "static_help.h"
int static_help()
{
printf("static help\n");
return 10;
}
上述两个文件,我们用命令把他制作为静态库,由于静态库是.o的集合,所以我们需要先编译出.o文件。通过下面的命令我们就能得到静态库文件libstatic_help.a。
gcc -c static_help.c -o static_help.o
ar -rc libstatic_help.a static_help.o
生成动态库:
// dynamic_help.h
#ifndef __DYNAMIC_HELP_H_
#define __DYNAMIC_HELP_H_
int dynamic_help();
#endif
// dynamic_help.c
#include <stdio.h>
#include "dynamic_help.h"
int dynamic_help()
{
printf("dynamic help\n");
return 100;
}
gcc -fPIC -shared dynamic_help.c -o libdynamic_help.so
如何使用第三方库
现在我们来看一下文件的位置:
库文件的位置我们main.c的代码如下:
#include <stdio.h>
#include "static_help.h"
#include "dynamic_help.h"
int main()
{
static_help();
dynamic_help();
return 0;
}
通常情况下我们的静态库和动态库和我们的代码目录不在一起,所以在编译的时候我们需要指定库的目录,可以这么写makefile文件
#指定库对应的头文件位置,最好使用绝对路径,而不是相对路径
INCLUDE=-I./dynamic_lib -I./static_lib
all:main
#用-L./dynamic_lib指定库的位置,最好用绝对路径
main:main.c
gcc $(INCLUDE) main.c -L./dynamic_lib/ -L./static_lib/ \
-ldynamic_help -lstatic_help -o main
.PHONY:clean
clean:
rm main
这样就编译好了我们的可执行程序main,接下来编写一个脚本run.sh来运行我们的代码。
#运行时,仅需要指定动态库的位置
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./dynamic_lib/
./main
#需要给这个脚本加上可执行权限:chmod 770 run.sh
#执行脚本:./run.sh
#执行结果:
#static help
#dynamic help
常见库报错
使用第三方库的时候经常会遇到以下这几种错误,这里单独列出来,也许,你在复盘上面的代码就会遇到。
- 找不到对于库的头文件,fatal error: static_help.h: 没有那个文件或目录,遇到这个错误说明你的代码包含了库的头文件,但是编译的时候找不到,需要在makefile里用-I./dynamic_lib这样的方式指定头文件位置。
- 找不到库文件 ,/usr/bin/ld: 找不到 -ldynamic_help
collect2: error: ld returned 1 exit status,遇到这个错误说明你使用了库里的函数,但是在编译的时候找不到函数地址,需要在makefile里用-L./dynamic_lib这样的方式指定。 - 找不到函数地址,main.c:(.text+0x14):对‘dynamic_help’未定义的引用,遇到这种情况说明,代码里使用了库函数,但是未把库引用进来,需要使用-ldynamic_help把库引入。
- 在你编译成功后,运行程序时,./main: error while loading shared libraries: libdynamic_help.so: cannot open shared object file: No such file or directory,说明你的执行环境里找不到动态库,换句话说你用了不在默认库路径下的库。需要用LD_LIBRARY_PATH来指定,在我们上面的栗子中就是语句export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./dynamic_lib/干的事情。
网友评论