静态链接库的创建和使用
本节先给大家讲解静态链接库的创建和使用,至于如何创建动态链接库,会在下一节做详细介绍。
假设当前有一个 C 语言项目,其目录结构如下所示:
demo项目 ├─ headers │ └─ test.h └─ sources ├─ add.c ├─ sub.c ├─ div.c └─ main.c
可以看到,该项目中包含 1 个头文件( .h ),4 个源文件( .c ),它们各自包含的代码如下所示:其中,headers 用于表示该项目拥有的所有头文件;sources 表示该项目拥有的所用源文件,读者可按照此目录结构构建 demo 项目,也可以将所有文件统一放置在 demo 项目下,本节选择的是后者,即将所有文件统一放置在 demo 目录下。
[root@bogon demo]# ls <- demo 目录结构
add.c div.c main.c sub.c test.h
[root@bogon demo]# cat test.h <- test.h 文件内容
#ifndef __TEST_H_
#define __TEST_H_
int add(int a,int b);
int sub(int a,int b);
int div(int a,int b);
#endif
[root@bogon demo]# cat add.c <- add.c 文件内容
#include “test.h”
int add(int a,int b)
{
return a + b;
}
[root@bogon demo]# cat sub.c <- sub.c 文件内容
#include “test.h”
int sub(int a,int b)
{
return a - b;
}
[root@bogon demo]# cat div.c <- div.c 文件内容
#include “test.h”
int div(int a,int b)
{
return a / b;
}
[root@bogon demo]# cat main.c <- main.c 文件内容
#include <stdio.h>
#include "test.h" //必须引入头文件
int main(void)
{
int m, n;
printf("Input two numbers: ");
scanf("%d %d", &m, &n);
printf("%d+%d=%d\n", m, n, add(m, n));
printf("%d-%d=%d\n", m, n, sub(m, n));
printf("%d÷%d=%d\n", m, n, div(m, n));
return 0;
}
[root@bogon demo]#
对于编译、运行 demo 项目,我们可以直接使用 gcc 命令完成:
[root@bogon demo]# gcc main.c add.c sub.c div.c -o main.exe
[root@bogon demo]# ls
add.c div.c main.c main.exe sub.c test.h
[root@bogon demo]# ./main.exe
Input two numbers: 10 2
10+2=12
10-2=8
10÷2=5
[root@bogon demo]#
注意,add.c、sub.c 和 div.c 这 3 个文件,其包含的都是一些功能模块(实现具体功能的函数),对于这样的源文件,只要我们愿意共享,每个人都可以直接用到自己的项目中。这就产生一个问题,如果仅希望别人使用我们实现的功能,但又不想它看到具体实现的源码,该怎么办呢?很简单,就是将它们加工成一个静态链接库。注意,由于在程序预处理阶段,GCC 编译器会自行处理各个 .c 文件内部引入的 .h 头文件(将 .h 文件中的代码直接拷贝到当前 .c 源文件中),因此编译运行 demo 项目时,我们只需要提供所有的源文件即可,不需要处理头文件。
静态链接库的创建
通过前面的学习我们知道,静态链接库其实就相当于压缩包,其内部可以包含多个源文件。但需要注意的是,并非任何一个源文件都可以被加工成静态链接库,其至少需要满足以下 2 个条件:- 源文件中只提供可以重复使用的代码,例如函数、设计好的类等,不能包含 main 主函数;
- 源文件在实现具备模块功能的同时,还要提供访问它的接口,也就是包含各个功能模块声明部分的头文件。
显然对于 demo 项目中的 add.c、sub.c 以及 div.c 这 3 个源文件来说,以上 2 个条件都符合,因此都可以被加工成静态链接库。并且根据实际需要,我们可以将它们集体压缩到一个静态链接库中,也可以各自压缩成一个静态链接库。
将源文件打包为静态链接库的过程很简单,只需经历以下 2 个步骤:
1) 将所有指定的源文件,都编译成相应的目标文件:
[root@bogon demo]# gcc -c sub.c add.c div.c
[root@bogon demo]# ls
add.c add.o div.c div.o main.c sub.c sub.o test.h
2) 然后使用 ar 压缩指令,将生成的目标文件打包成静态链接库,其基本格式如下:
ar rcs 静态链接库名称 目标文件1 目标文件2 ...
有关 ar 打包压缩指令,以及 rcs 各选项的含义和功能,感兴趣的读者可自行查找相关资料了解。这里需要重点说明的是,静态链接库的不能随意起名,需遵循如下的命名规则:libxxx.a
其中,xxx 代指我们为该库起的名字,比如 Linux 系统自带的一些静态链接库名称为 libc.a、libgcc.a、libm.a,它们的名称分别为 c、gcc 和 m。Linux 系统下,静态链接库的后缀名为 .a;Windows 系统下,静态链接库的后缀名为 .lib。
下面,我们尝试将 add.o、sub.o 和 div.o 打包到一个静态链接库中:
[root@bogon demo]# ar rcs libmymath.a add.o sub.o div.o
[root@bogon demo]# ls
add.c add.o div.c div.o libmymath.a main.c sub.c sub.o test.h
通过以上 2 步操作,我们就成功创建出了 libmymath.a 静态链接库。那么,该如何使用它呢?
静态链接库的使用
静态链接库的使用很简单,就是在程序的链接阶段,将静态链接库和其他目标文件一起执行链接操作,从而生成可执行文件。以 demo 项目为例,首先我们将 main.c 文件编译为目标文件:
[root@bogon demo]# gcc -c main.c
[root@bogon demo]# ls
add.c div.c libmymath.a main.o sub.c
test.h add.o div.o main.c sub.o
在此基础上,我们可以直接执行如下命令,即可完成链接操作:
[root@bogon demo]# gcc -static main.o libmymath.a
[root@bogon demo]# ls
add.c a.out div.o main.c sub.c test.h
add.o div.c libmymath.a main.o sub.o
注意,如果 GCC 编译器提示无法找到 libmymath.a,还可以使用如下方式完成链接操作:
[root@bogon demo]# gcc main.o -static -L /root/demo/ -lmymath
[root@bogon demo]# ls
add.c a.out div.o main.c sub.c test.h
add.o div.c libmymath.a main.o sub.o
由此,就生成了 a.out 可执行文件:
[root@bogon demo]# ./a.out
Input two numbers: 10 2
10+2=12
10-2=8
10÷2=5
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算