一、静态库和动态库

静态库是指程序在编译阶段就把库文件嵌入到程序中的三方库,这种行为在程序运行前就已经决定了,程序在编译完成后不再依赖库文件。

动态库和静态库不一样,它是在程序运行期间才发生的调用行为,不会嵌入到程序,相对来说,链接动态库的二进制文件体积更小。

windows和linux平台下的静态/动态库后缀分别为lib dll.a .so,其中linux中动态库的命名规则为:libxxx.so.x.y.z,xxx表示库名,x是主版本号,y是此版本号,z是发行版本号。

二、静态库的使用

创建一个三方库的源文件func1.c

#include <stdarg.h>

int add(int x, int y) {
    return x + y;
}

int sum(int cnt, ...) {
    int sum = 0;
    va_list ap;
    va_start(ap, cnt);
    while(cnt--)
        sum += va_arg(ap, int);
    va_end(ap);
    return sum;
}

生成目标文件:

> gcc -c func1.c # 此时会生成.o文件
> ls
func1.c func1.o

将目标文件生成库文件:

> ar cr libfunc1.a func1.o # 文件名一定要是libxxx.a
> ls # 此时会生成静态库文件
func1.c  func1.o  libfunc1.a

编写主文件main.c

#include <stdio.h>

// 声明库中的函数,也可以写在头文件中包含。
int add(int, int);
int sum(int, ...);

int main() {
    printf("%d\n", add(1, 2));
    printf("%d\n", sum(5, 1, 2, 3, 4, 5));

    return 0;
}

编译主程序:

gcc main.c -L. -lfunc1 -o app 

-l选项后面加库名表示要链接的库,系统默认在系统的库文件目录(/lib, /usr/lib, /usr/local/lib)中查找,如果库文件不在这几个目录中,则要通过-L文件指定目录。

编译好后运行(删除libfunc1.a文件程序依旧可以运行):

> ./app 
3
15

三、动态库的使用

依旧使用上面的func1.c文件,编译动态库:

> gcc -fPIC -c -o func1.o func1.c # 生成.o文件
> gcc -shared -o libfunc1.so func1.o  # 生成动态库

上述步骤也可以缩成一步:

> gcc func1.c -fPIC -shared  -o libfunc1.so

执行完后将会生成一个libfunc1.so

> ls
ma@ubuntu:/code/code/Makefile$ ls
func1.c  func1.o  libfunc1.so  main.c

编译主程序:

> gcc main.c -lfunc1 -o app
/usr/bin/ld: cannot find -lfunc1
collect2: error: ld returned 1 exit status

执行会报错,找不到库func1,添加上-L选项:

> gcc main.c -lfunc1 -o app -L. # 成功编译
> ./app # 运行出错
./app: error while loading shared libraries: libfunc1.so: cannot open shared object file: No such file or directory

加上-L选项后能完成编译,但是运行时还是找不到动态库,此时的解决方法可以查看:''xxx'': error while loading shared libraries的解决方案,解决依赖后运行程序:

最后修改:2018 年 12 月 16 日
如果觉得我的文章对你有用,请随意赞赏