到目前为止,我们穿着较小程序的工作,但是当我们创建一个非常大的程序时,我们面临一些问题,例如
-
汇编和链接的整体时间增加。
-
污染Makefile。
-
污染我们放置源文件的目录。
当我们面对这个问题时,我们可能会看到将源代码组合到相关文件的小单位中的一种方式。
#什么是“ C”库
库是一个包含几个对象文件的文件,在程序的链接阶段中使用。
为什么使用库的
-
库是索引的,因此很容易找到函数,变量和其他
-
链接在库中订购的对象文件的程序比链接对象的程序更快。
-
加快链接
我们可以创建两种类型的库的
-
静态库
-
共享(或动态)库
静态库
是在编译的链接阶段链接到程序的对象文件,并且在运行时不使用。
在创建可执行文件静态库的创建期间,在源代码中复制了静态库,因此我们只能使用可执行文件运行程序。
静态链接的缺点是文件的大小会增加,因此,由于创建文件具有单独运行所需的一切,因此保持应用程序的更新很难,我们需要每次使用程序时重新编译。<<<<<<<<<<<< /p>
中的静态库
-
Windows有一个
.lib
(库)扩展 -
Linux有一个
.a
(存档)扩展
共享库(动态库)
是在编译的链接阶段和运行时链接到程序的对象文件。
在程序的编译时间中,共享库用于验证程序所需的所有函数,变量和其他功能都链接到程序中,或者在其共享库之一中链接。
。在程序的运行时间内,共享库将通过程序加载到内存。
当我们创建文件的可执行文件时,共享库的地址存储在最终可执行文件中。
动态链接的某些缺点正在启动该程序稍微慢,当我们重新编译程序时,我们面临的问题是先前库的副本,该副本已经存储在内存中。
动态库通过静态墨水解决了一些问题,例如大小和编译需求。
中的碎片库
-
Windows有一个
.dll
(动态链接库)扩展 -
linux有一个
.so
(shard对象)扩展
#创建静态“ C”库
我们可以使用名为“ AR”的程序创建一个静态库,用于“ Archiver”。
要创建静态库,请使用命令:
ar rc static_lib.a factorial.o mult.o
此命令使用两个对象文件的fortorial.o和mult.o创建一个名为static_lib.a的静态库,r
告诉Archiver用新的对象文件替换库中的旧对象文件,c
告诉Archiver创建创建如果库不存在。
创建一个对象文件表格c文件使用命令
gcc -g -O -c factorial.c
gcc -g -O -c mult.c
现在,我们创建了需要索引的静态库。
编译器用索引来加快库中的符号 - 函数(例如函数,可变等)。
用于创建或更新索引的命令称为“ Ranlib”,被称为
ranlib static_lib.a
有关更多信息,请使用命令
man ar
和man ranlib
#在程序中使用“ C”库
到目前为止,我们了解了创建静态库,现在我们想在程序中使用此库。
gcc main.c static_lib.a
在此示例中,我们将在需要static_lib.a库时编译main.c程序。
#创建共享的“ C”库
共享(Dynamic)库具有与静态库相同的创建过程,但是它以两种方式
有所不同。- 在创建库的对象文件时,我们必须使用“
-fPIC
或-fpic
”,这些标志是“位置独立代码”(PIC)来使用内存的相对地址,因为许多不同的程序可能会将程序加载到其他位置中记忆。
gcc -fPIC -c factorial.c
gcc -fPIC -c mult.c
- 与静态库不同,共享库不是一个存档文件,因此必须专门针对正在创建的操作系统量身定制。
我们可以根据编译器使用
-G
标志或-shared
标志。
gcc -shared shared_lib.so factorial.o mult.o
在此示例中,我们使用flag -shared
使用对象文件fortorial.o和mult.o创建名为shared_lib.so
的共享库,通过查看扩展名为.os
,我们可以得出结论,该库在linux上运行。<<<<<<<<<<<<<<<<<<<<<<<<<< /p>
#使用共享的“ C”库
正如我们提到的,我们在两种情况下使用共享库:
- 编译时间 - 告诉链接器在构建可执行程序时扫描共享库。 它与静态库相同
gcc main.c shared_lib.os
- 运行时间 - 告诉加载程序在哪里找到我们的共享库。
在运行时间使用时,使用共享库有点棘手。
我们可以使用'ld_library_path'环境变量来告诉加载程序在其他目录中查看。
在
bash
中
LD_LIBRARY_PATH=/full/path/to/library/directory
export LD_LIBRARY_PATH
#使用dlopen()加载共享库
要加载并打开共享(动态)库,我们使用dlopen()函数。
示例
#include <dlfcn.h> /* defines dlopen(), etc. */
int main(void)
{
void* lib_handle; /* handle of the opened library */
lib_handle = dlopen("/full/path/to/library", RTLD_LAZY);
if (!lib_handle) {
fprintf(stderr, "Error during dlopen(): %s\n", dlerror());
exit(1);
}
}
dlopen()采用两个参数,第一个是通往共享库的完整路径,第二个参数用于检查是否需要立即检查库的符号(rtld_local),或仅在使用时(rtld_lazy)。