欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux下GCC静态动态链接库的使用

程序员文章站 2022-05-13 09:49:58
...


本篇讲述Linux下如何利用GCC来制作和使用静态链接库以及动态链接库。

1.静态链接库与动态链接库

早期的共享库以源代码的形式进行,但是由于源代码的方式不利于商业化,即商业公司希望用户使用自己发布的库的同时,不泄露自己的源代码,由此产生了库这样的东西。库主要有以下两种形式:

  • 静态链接库
  • 动态链接库
  • 静态库是出现的比较早的,其本质就是源代码经过只编译不链接形成的中间目标文件(.o文件),通过ar这个工具来归档成.a文件,这个文件就是静态链接库。用户通过.a文件和.h头文件来使用该库,用户拿到这两个文件后,通过.h头文件得知.a文件中的函数原型,然后在自己的代码中包含该头文件,调用其中的函数,在链接的时候链接器会去.a文件中寻找对应的.o文件,最终链接成可执行文件。
  • 动态库比静态库出现晚但是效率更高。静态库在被链接时,把已调用的库的代码复制进了可执行程序中,这会使程序占用非常大的空间。当程序重复调用该函数时,这些代码也会被重复复制。动态链接库不是直接复制,而是做了个链接标记,当程序运行时发现自己调用了一个动态链接库中的函数时,会加载这个库到内存中,以后不管多少个程序在调用这个库,内存中只会有一份该库。

2.制作一个静态链接库

假设我们有一个add函数,我们在.h头文件里写上函数声明,在.c源文件里写上函数定义:

add.h:

#include<stdio.h>

int add(int a,int b);

add.c:

#include"add.h"

int add(int a,int b)
{
    return a+b;
}

制作这个函数的静态库需要经过两步:
首先利用gcc生成.o文件:

gcc -c add.c add.h 

然后使用ar工具生成静态库:

 ar -rc libadd.a add.o

这样就制作好了一个名字为libadd.a的静态文件。一般静态库的名字就是libxxx.a,xxx对应xxx.o。

3.使用静态库

我们首先写一个代码来使用上面的add函数:
test.c:

#include"add.h"

int main(int argc,char**argv)
{
    int a,b;
    printf("现在测试加法,请输入两个整数:\n");
    scanf("%d %d",&a,&b);
    printf("%d + %d = %d\n",a,b,add(a,b));

    return 0;   
}

然后使用如下命令来编译链接该文件,其中-ladd指定依赖的静态库名,这里不需要加.a后缀名:

 gcc -o test  testLib.c -ladd

发现报错:

/usr/bin/ld: cannot find -ladd
collect2: error: ld returned 1 exit status

这是因为当使用-lxxx参数时,链接器会尝试去默认的目录内寻找lxxx.a文件,而当前目录不属于默认目录,所以需要给它指定相应的目录。指定目录使用L参数,具体如下:

gcc -o test  test.c -ladd -L.

其中L后面的.表示当前目录。至此编译链接出可执行文件,通过ls -la命令可以看到,生成的test文件大小为8504字节。

4.制作动态链接库

同样的对于上面的add函数,我们使用如下命令来制造对应的动态链接库:

gcc -c add.h add.c -fPIC
gcc -o libadd.so add.o -shared

其中-fPIC是位置无关编译方式来生成.o文件,-shared是按共享库的方式来链接。这样我们就制作出了一个名为libadd.so的动态库文件。

我们再来编译test.c,命令如下:

 gcc test.c -ladd -L. -o test

发现test大小为8472字节,比静态库要小,小的不明显是因为这里只有一个函数,并且该函数也只调用了一次。