说的库,实质就是一些库函数,在我们编程的时候会用到,这样我们就可以避免重复写一此代码了。如: c/c++中的标准输入输出函数等,我们都是用得它们的库;
静态库就是我们在编译我们的函数时,直接把要用的库的内容编译包含进去了,使它们成了一体了;而动态库呢,我们编译我们函数的时候不会直接把要使用到的库的内容包含进去,而是运行的时候再调用它;至于它们的缺点,用脑子想想就一目了然了。
静态库:
以 .a 为后缀,意思为 archive 文件;静态库通过命令 ar 得到; 命令 ar 把源码经过预处理、编译、汇编得到的 .o 文件通过包含起来,可以多个 .o 文件;
例如:在我们写C程序时,它会默认包含了C标准库 /usr/lib/libc.a,里面有ANS1/ISO标准指定的函数,比如printf。所以我们不用再手动链接了;如果使用标准指定的函数以外的函数,这时我们要手动链接上相关的库了,如数学静态库 libm.a (头文件为 math.h)
ar 的命令:
以后补充;
/****/
举例:下面写一个 libhello.a 的静态库,然后通过 main.c函数调用;
编写 hello.h, 目的为了让用户知道我们的动态库中有哪些接口可用。
#ifndef __HELLO_H__ #define __HELLO_H__ void hello(); #endif编写 hello.c
#include <stdio.h> #include "hello.h" void hello() { printf("hello, world "); }生成 hello.o 目标文件
gcc -o hello.o -c hello.c
生成 libhello.a 静态库
ar -cqs libhello.a hello.o
编辑 main.c文件
#include "hello.h" int main(int argc, char** argv) { hello(); return 0; }现在使用静态库把 main.c 生成最后的可执行代码:
gcc –o Out main.c –L ./ –l hello注意:上面中的 –L :追加目录到库文件的搜索路径中; –l :指定使用的库文件,其中的库名 将前缀lib和后缀.a(或.so)省略。
运行代码,查看结果:
./ Out hello,world!
动态库:
文件名形如
libxxx.so
,其中so是 Shared Object 的缩写,即可以共享的目标文件。生成动态库常用 gcc 命令;
举例:
编写头文件:ok.h 文件
#ifndef __OK_H__ #define __OK_H__ void ok(); #endif编写 ok.c 文件
#include "ok.h" int main(int argc, char** argv) { ok(); return 0; }生成动态库
gcc –fPIC –shared –o libok.so ok.c编写 test.c 测试文件
#include "ok.h" int main(int argc, char argv**) { ok(); return 0; }利用动态库生成可执行文件;
gcc -o Out test.c -L ./ –l ok注意:上面中的 –L :追加目录到库文件的搜索路径中; –l :指定使用的库文件,其中的库名 将前缀lib和后缀.a(或.so)省略。
现在运行:Out 可执行文件;
yinheyi@ubuntu:~/play$ ./Out ./Out: error while loading shared libraries: libok.so: cannot open shared object file: No such file or directory先解决存在问题:这个Out 运行时,它的库的搜索路经不包括当前目录吧(上面用-L 追加的目录只用于生成Out文件的,和运行时没有关系),所以呢,
1. 我们可以把 libok.so 库文件放到搜索目录中去:/usr/lib 或 /lib;
2.也可以临时添加当前搜索路经:
export LD_LIBRARY_PATH=`pwd`3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径;动态装入器将在其中查找共享库。注意:
/etc/ld.so.conf
中并不必包含/lib
和/usr/lib
,因为ldconfig
程序会自动搜索这两个目录。
- 1)把库路经放入 /etc/ld.so.conf文件中;
- 2)运行ldconfig 生成最新的 /etc/ld.so.cache 文件;
本文采用方法二以后再次运行,成功:
yinheyi@ubuntu:~/play$ ./Out Are you OK??