首先要理解,我们通常将一些通用函数写成函数库,库是现有的,成熟的,可以复用的代码,是一种可执行代码的二进制形式,可以被操作系统载入内存执行。为了提高开发效率,我们在coding时经常会使用各种各样的库。而库又区分为静态库和动态库(都由.o文件生成)!还有一个使用库的原因是某些开发公司需要用代码盈利,便把源码编译成库文件的形式提供给客户使用,而客户不会知道使用的函数功能是如何实现的。
一、静态库
①特点
静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库
优点:在编译后的执行程序不在需要外部的函数库支持,因为所使用的函数都已经被编译进去了
缺点:如果所使用的静态库发生更新改变,你的程序必须重新编译
②命名(“libxxx.a”)
“libxxx.a”,xxx库名前加“lib”,后缀为“.a”
③生成过程(ar -rcs libxxx.a *.o)
以打印hello,linux!为例:
hello.c
#include <stdio.h>
#include "hello.h"
int func(void)
{
printf("hello,linux!\n");
return 0;
}
hello.h
#ifndef HELLO_H
#define HELLO_H
extern int func(void);
#endif
main.c
#include "hello.h"
int main(void)
{
func();
return 0;
}
gcc -c hello.c(生成.o文件)
ar -rcs libhello.a *.o(生成静态库)
gcc main.c -o main -L. -lhello(生成可执行文件)
-l(小写的l):指定要链接的库,会到/lib和/usr/lib和/usr/local/lib的系统路径下去找库,显然我们要链接的库在当前路径下,并没有copy到系统路径,故只用-l会报错,要加上-L.
-L:指定要链接的库的路径,-L.即为当前路径
./main
此时就算删除静态库,对可执行文件也没有影响,因为他们已经融为一体
二、动态库
①特点
动态库在编译的时候并没有被编译进目标代码,而是当你的程序执行到相关函数时才调用该函数库里的相应函数
优点:动态库的改变并不影响已编译的程序,所以动态函数库升级比较方便
缺点:函数库并没有整合进程序,所以程序的运行环境必须提供相应的库
②命名(“libxxx.so”)
“libxxx.a”,xxx库名前加“lib”,后缀为“.so”
③生成过程(gcc -shared -fPIC -o libxxx.so *.o)
gcc -shared -fPIC -o libhello.so *.o(生成动态库)
gcc main.c -o main -L. -lhello(与上文的静态库一样,生成可执行文件)
./main(会报错哦)
程序在运行时,会在/usr/lib和/lib等系统路径中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行
想要解决这个问题
1.可以把动态库move到系统路径下
mv libxxx.so /usr/lib
2.无sudo权限,可以使用export,在LD_LIBRARY_PATH环境变量中添加库所在路径(暂时的添加,下次启动linux时已不存在)
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.(.即为当前路径)
./main
成功执行!
补充:当静态库和动态库同名时, gcc命令将优先使用动态库