Skip to content

Commit f8d853b

Browse files
ustcljhtaoky
authored andcommitted
Add overview ans static linked library.
1 parent 7309688 commit f8d853b

File tree

2 files changed

+119
-0
lines changed

2 files changed

+119
-0
lines changed

docs/dev/library.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
---
2+
icon: simple/cplusplus
3+
---
4+
5+
# 链接库
6+
7+
!!! note "主要作者"
8+
9+
[@luojh][luojh]
10+
11+
!!! warning "本文编写中"
12+
13+
!!! comment "适用范围"
14+
15+
本文介绍 Linux 上的**静态链接库** (一般为 `.a` 文件) 和**动态链接库** (一般为 `.so` 文件)。注意:这里的链接库是指包含了可执行二进制代码的库,并不是头文件 (Header file)、Python 库等。
16+
17+
## 总览
18+
19+
库 (Library),是包含**可重用代码和数据**的模块。
20+
21+
### 构建链接库
22+
23+
下图给出了一般的可执行文件 (executable)、静态链接库 (static library)、动态链接库 (dynamic library) 的构建过程。
24+
25+
```mermaid
26+
flowchart TD
27+
28+
source["源文件 (*.c, *.cpp)"] -->|编译| target["目标文件 (*.o)"]
29+
header["头文件 (*.h)"] --- source
30+
target -->|链接| executable["可执行文件 (ELF等)"]
31+
target -->|ar rcs| staticlib["静态链接库 (*.a)"]
32+
target -->|gcc -shared| dynamiclib["动态链接库 (*.a)"]
33+
```
34+
35+
### 使用链接库
36+
37+
下图给出了**使用链接库**的方式。
38+
39+
```mermaid
40+
flowchart TD
41+
source["源文件 (*.c, *.cpp)"] -->|编译| target["目标文件 (*.o)"]
42+
header["头文件 (*.h)"] --- source
43+
target --> linker["链接器"]
44+
staticlib["**静态链接库** (链接步骤加入)"] --> linker
45+
linker --> executable["可执行文件 (ELF等)"]
46+
dynamiclib["**动态链接库** (运行时加载)"] --> executable
47+
```
48+
49+
## 源代码
50+
51+
对于 C 程序而言,链接库的源代码就是普通函数、变量之类,并无太多特殊要求。例如,创建并进入目录 `lib`,在 `square.c` 源文件中写一个函数 `square`
52+
53+
```c
54+
int square(int x)
55+
{
56+
return x * x;
57+
}
58+
```
59+
60+
对应的,需要在头文件 `square.h` 中加入这个函数的原型 (prototype)
61+
62+
```c
63+
int square(int x);
64+
```
65+
66+
以便其他使用链接库的程序**知道如何使用这个函数** (即使这些程序不知道函数内部的实现)。
67+
68+
因为链接库不是完整的、可以独立运行的程序,因此不需要入口点 (比如 `main` 函数)。
69+
70+
## 静态链接库
71+
72+
静态链接库是在**链接步骤就加入**的链接库类型。
73+
74+
### 构建
75+
76+
首先按照正常方法编译得到 `.o` 文件:
77+
78+
```shell
79+
gcc square.c -c -o square.o
80+
```
81+
82+
然后使用 `ar` 程序创建静态链接库 `libsquare.a`
83+
84+
```shell
85+
ar rcs libsquare.a square.o
86+
```
87+
88+
注意这里的 `libsquare.a` 是命名惯例:一般静态链接库的文件名需要为 `lib<名称>.a`
89+
90+
到这里就完成了静态链接库的创建。
91+
92+
### 使用
93+
94+
另一个 C 程序 `main.c` 中使用了 `square` 函数,那么首先需要包含 `square.h` 头文件,这样才能知道这个函数的原形,然后就可以正常调用了。
95+
96+
```c
97+
#include <main.c>
98+
#include "lib/square.h"
99+
100+
int main(void)
101+
{
102+
int a;
103+
scanf("%d", &a);
104+
105+
printf("%d^2 = %d\n", a, square(a));
106+
return 0;
107+
}
108+
```
109+
110+
下面的命令可以将这个程序直接编译-链接到可执行文件 `main` (也可以分开成单独的编译步骤、链接步骤)。
111+
112+
```shell
113+
gcc main.c -L./lib -lsquare -o main
114+
```
115+
116+
这里,`-L./lib` 表示要求链接器在 `./lib` 中寻找链接库,`-lsquare` 表示需要链接 `libsquare.a` 这个头文件。
117+
118+
编译好之后,就可以正常使用了。由于静态链接库中的代码会被直接合并到链接产生的可执行文件 `main` 中,因此运行时不需要文件 `libsquare.a`

includes/authors.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@
2323
[zeyugao]: https://github.com/zeyugao
2424
[relic-yuexi]: https://github.com/relic-yuexi
2525
[Jerry-Kwan]: https://github.com/Jerry-Kwan
26+
[luojh]: https://github.com/luojh

0 commit comments

Comments
 (0)