C-静态库
#初学者 #c #库 #静态

到目前为止,我们穿着较小程序的工作,但是当我们创建一个非常大的程序时,我们面临一些问题,例如

  • 汇编和链接的整体时间增加。

  • 污染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 arman 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)。