Linux C/C++编程之静态库

10.3.1  静态库的基本概念

静态库文件的后缀为.a ,在Linux 下一般命名为libxxx.a 。当有程序使用某个静态库时,在链接步骤中,链接器将从静态库文件中取得的代码复制到生成的可执行文件中,即整个库中的所有函数都被链接到可执行文件中。因此使用静态库的可执行文件通常较大。但使用静态库的优点也非常明显,即可执行程序最终运行时不需要和该库有关的文件的支持,因为所有使用的函数都已经被编译进去了,可执行文件可以直接运行。当然,有时候这也是一个缺点,比如静态库里的内容改变了,那么程序(调用者)必须重新编译。

10.3.2  静态库的创建和使用

通常使用ar 命令来创建静态库。通过ar 命令其实就是把一些目标文件(.o )组合在一起,成为一个单独的静态库。Linux 上创建静态库的步骤如下:

1 )编辑源文件(比如.c .cpp 文件)。

2 )通过gcc -c xxx.c g++ -c xxx.cpp 生成目标文件(即.o 文件)。

3 )用ar 归档目标文件,生成静态库。

4 )配合静态库写一个头文件,文件里的内容就是提供给外面使用的函数、变量或类的声明。

要学会创建静态库,主要是学会ar 命令的使用。ar 命令不但可以创建静态库,还可以修改或提取已有静态库中的信息。它的常见用法如下:

ar [option] libxxx.a xx1.o xx2.o xx3.o ...

其中,option ar 命令的选项;libxxx.a 是生成的静态库文件的名字,xxx 通常是我们自己设定的名字,lib 是一种习惯,静态库通常以lib 开头;后面的xx1.o xx2.o xx3.o 是要归档进静态库中的目标代码文件,可以有多个,所以后面用省略号。

常用选项如下:

1 )选项c :用来创建一个库。无论库是否存在,都将创建。

2 )选项s 创建目标文件索引,这在创建较大的库时能加快时间。如果不需要创建索引,可改成大写S 参数;如果.a 文件缺少索引,还可以使用ranlib 命令添加。

3 )选项r 在库中插入模块,若插入的模块名已经在库中存在,则将替换同名的模块。如果若干模块中有一个模块在库中不存在,ar 就会显示一个错误消息,并不会替换其他同名模块。默认情况下,新的成员增加在库的结尾处,可以使用其他任意选项来改变增加的位置。

4 )选项t 显示库文件中有哪些目标文件。注意,只显示名称。

5 )选项tv 显示库文件中有哪些目标文件。显示的信息包括文件名、时间、大小等。

6 )选项s 显示静态库文件中的索引表。

要使用静态库很简单,下面我们来看一个例子,生成一个静态库并使用它。

【例10.1 】创建并使用静态库(g++ 版)

1 )打开Visual Studio Code ,新建一个源文件test.cpp ,内容如下:

#include 

#include

using namespace std;

void f(int age)

{

    cout << "your age is " << age << endl;

    printf("age:%d\n",age);

}

代码很简单。这个源码文件主要作为静态库。我们首先 test.cpp 文件 上传到Linux ,在命令行 输入 以下命令

# g++ -c test.cpp

此时会在test.cpp 同目录下生成test.o 目标文件 再输入 以下 命令来生成静态库:

# ar rcs libtest.a test.o

其中,ar 是静态函数库创建的命令,c create (创建)的意思,rs 前面都有解释。

此时会在同目录下生成libtest.a 静态库文件。注意,所要生成的.a 文件的名字前3 位最好是lib ,否则在链接的时候,就可能找不到这个库。

2 )现在静态库生成了,我们另外编写一个源文件来使用该库中的函数f 。打开Visual Studio Code ,新建一个文件main.cpp ,并输入如下代码:

extern void f(int age);   // 声明要使用的函数

#include

using namespace std;

 

int main(int argc, char *argv[])

{

    f(66);

    cout << "HI" << endl;

    return 0;

}

代码很简单。首先声明一下f ,然后就可以在main 函数中使用了。保存文件后将其上传到Linux ,注意要和libtest.a 放在同一个目录,然后在命令行进行编译并运行:

# g++ -o main main.cpp -L. -ltest

# ./main

your age is 66

age:66

HI

编译运行成功了。其中,-L 用来告诉g++ 去哪里找库文件,它后面加了一个点(. ),表示在当前目录下去找库文件; -l 用来指定具体的库,其中的lib .a 不用显式写出,g++ gcc 会自动去寻找libtest.a ,这也是我们前面生成静态库的时候,静态库的文件名要用lib 前缀的原因。默认情况下,g++ gcc 首先搜索动态库(.so )文件,找不到后再去寻找静态库(.a )文件。当前目录没有动态库文件,因此可以找到静态库文件。

gcc g++ 使用静态库的过程类似,下面列举一个gcc 版本的例子。

【例10.2 】创建并使用静态库(gcc 版)

1 )打开Visual Studio Code ,新建一个源文件test.cpp ,内容如下:

#include 

void f(int age)

{

    printf("age:%d\n",age);

}

这个源码文件主要作为静态库。我们首先 test.c 文件 上传到Linux ,在命令行 输入 如下命令

# gcc -c test.c pp

此时会在test.cpp 同目录下生成test.o 目标文件 再输入 以下 命令来生成静态库:

# ar rcs libtest.a test.o

此时会在同目录下生成libtest.a 静态库文件。

2 )现在静态库生成了,我们另外编写一个源文件来使用该库中的函数f 。打开Visual Studio Code ,新建一个文件main.cpp ,并输入如下代码:

extern void f(int age);   // 声明要使用的函数

 

int main(int argc, char *argv[])

{

    f(66);

    return 0;

}

代码很简单 首先声明一下f ,然后就可以在main 函数中使用了。保存 代码 将其 上传到Linux ,注意要和libtest.a 放在同一个目录,然后在命令行进行编译并运行:

# gcc -o main main.c pp -L. -ltest

# ./main

age:66

编译运行成功了。其中,-L 用来告诉gcc 去哪里找库文件,它后面加了一个点(. ),表示在当前目录下去找库文件;-l 用来指定具体的库,其中的lib .a 不用显式写出,g++ gcc 会自动去寻找libtest.a 。默认情况下,g++ gcc 首先搜索动态库(.so )文件,找不到后再去寻找静态库(.a )文件。当前目录没有动态库文件,因此可以找到静态库文件。


请使用浏览器的分享功能分享到微信等