实施静态库

C编程语言支持动态库和静态库。 尽管动态库有其优势-特别是在它们维护较短的源代码文件方面-但今天,我将重点关注静态库。

为了更好地理解静态库,您必须了解四个重要概念:

  • 为什么要使用库
  • 他们如何工作
  • 如何建立它们
  • 如何使用

静态库是包含目标代码的文件。 它们之所以有用,是因为通过将源代码文件与静态库链接,我们可以访问静态库中包含的任何代码。 例如,如果我们需要访问源代码文件中的10个不同函数,而不是创建10个不同文件(每个函数1个)并包括其中的每个文件,我们可以简单地创建一个包含这些函数的静态库,然后链接我们的静态文件。库到我们的源代码文件。

让我们从头到尾做到这一点。

看看我们的主要功能

在这里,我们创建了一个主函数,该函数使用一行文本调用_puts()函数。

看_puts实现。 请注意,_puts()中使用了_putchar()。

这是_puts()函数的实现。 为了使main()函数正常工作,我们可以创建一个静态库,并将_puts()函数的实现包含在我们的标准库中。 您可能已经注意到,_puts()函数调用_putcar()函数,这意味着我们还必须在静态库中包含_putchar()函数的实现。

首先,我们需要确保_putchar.c和_puts.c文件存在于当前目录中。 为此,我们可以运行ls命令,然后输入这两个文件的名称。 如果它们在当前目录中不存在,我们可以使用find命令找到它们。

find命令返回我们要包含在静态库中的函数的文件路径

找到所需文件后,可以使用cp命令将其移至当前目录。 在这种情况下,cp命令比mv命令更可取,因为使用cp命令,您仅移动文件的副本。 这意味着原始文件将不会离开其创建所在的目录。

将3-puts.c的副本移到所需目录中

现在,我们可以返回static_library_ex目录,在其中创建我们的静态库。 静态库的强大优势之一在于它们已经过预编译。 这意味着您在静态库中编写的所有代码都将被编译为目标代码。 在实现方面,这可能是一个很大的优势,因为当您调用静态库来执行任务时,无需在运行时编译或加载任何内容。 这意味着静态库很快。

这也意味着,为了创建静态库,我们必须首先将要包含在静态库中的所有文件编译为目标代码。

将我们将放在静态库中的文件编译为目标代码

在这里,“-c”标志在链接程序运行之前暂停gcc编译过程(要了解有关gcc编译过程中步骤的更多信息,请在此处查看我的最后一篇博客文章)。 这意味着,在运行汇编程序之后,gcc编译器将停止运行,从而使您剩下多个用目标代码编写的单独文件。

如果您已经了解此过程并希望节省时间,则可以使用以下bash脚本在静态库中找到要包含的文件,并将其从当前目录编译为目标代码:

如果您不了解此脚本,则可能不要使用它

现在,我们已经拥有了希望包含在当前目录的静态库中并已编译为目标代码的所有文件,现在可以创建静态库了。 在此示例中,我们将创建一个名为libexample.a的静态库。 我们的库具有“ .a”扩展名,因为它是Linux环境中静态库的适当扩展名。

用于将文件添加到静态库的命令是ar-存档的缩写。 存档是包含其他文件的文件。 但是ar命令允许我们将文件添加到我们的标准库中。

命令ar rc libexample.a 3-puts.o _putchar.o将对象代码添加到我们的标准库中

如果名称匹配,则“ r”选项告诉静态库将其持有的任何目标文件替换为要添加的新目标文件。 “ c”选项告诉linux如果所提供的名称不存在,则创建一个静态库。

在第二个命令“ ar -t libexample.a”中,“ t”标志告诉linux列出静态库的所有内容。 在我们的例子中,我们可以看到3puts.o和_putchar.o已添加到我们的静态库中。

在将所有内容添加到我们的标准库之后,需要对库进行索引。 可以通过运行命令ranlib libexample.a完成对该库的索引。 为库建立索引很重要,因为它可以在调用库时加快链接过程。

我们可以通过运行命令nm libexample.a查看我们最近生成的索引。

“ T”表示“符号位于目标文件的文本部分中”。“ U”未定义。

现在—最后,我们准备使用我们的库。 要使我们的主要功能可以访问libexample.a,我们运行以下简单命令: gcc main.c -L。 -lexample -o main

gcc标志“ -l”指示目标文件与静态库链接(请注意,此处不需要“ lib”前缀和“ .a”扩展名)。 gcc标志“ -L”告诉目标文件在某个目录中查找静态库。 在我们的例子中,我们将“。”包括在内,因为静态库与目标文件位于同一目录中。

有用

如果我们忘记了“。”,我们的目标文件将无法链接到我们的静态库,并且会出现错误。

找不到_puts()的实现,因为找不到libexample.a

这就是从头到尾创建和实现静态库的方式。 最后,我将给您留下最后的笔记。 如果选择编辑_puts()或_putchar()函数,则必须重新编译它们,然后将它们重新添加到静态库中(如果希望看到它们的更改生效)。