静态库包含C语言中的问题

时间:2012-12-02 01:54:03

标签: c gcc static-libraries

我按照以下教程创建了一个静态库。

http://tldp.org/HOWTO/Program-Library-HOWTO/static-libraries.html

http://www.adp-gmbh.ch/cpp/gcc/create_lib.html

http://www.cs.dartmouth.edu/~campbell/cs50/buildlib.html

我使用ar工具在C中生成了一个静态库。该库来自不同的目录。我正在正确地生成库,并且我使用它来编译我的程序,如下所示:

gcc -lpthreads main.c -o server -L thread-pool -lthreadpool

当前目录下的库名为thread-pool,其中包含libthreadpool.a

根据教程,我需要在.hmain.c中包含我的#include "threadpool.h"文件,如下所示。海湾合作委员会抛出一个错误,说找不到threadpool.h。这很明显,因为它位于不同的目录中。

当我将其包含为:#include threadpool/threadpool.h"时,它会编译,但实际上并不起作用。它仍然无法识别这些功能。我不确定为什么会这样。我想在编译静态库时,您不需要实际发送.h文件或任何来源。

这是什么问题?我怎么能克服这个?

修改

我知道.h文件与静态库不同。我不确定为什么我上面说的话似乎让我感到困惑。

无论如何,当一个人使用静态库时,是否意味着我们还需要.h文件并将其包含在源代码中,而不仅仅是用静态库编译程序?

2 个答案:

答案 0 :(得分:4)

库和标题是两个不同(虽然相关)的东西。您也可以使用编译器选项解决您的问题,为编译器提供一个额外的目录来查找标题:

gcc -lpthreads -I threadpool main.c -o server -L thread-pool -lthreadpool

由于您的threadpool库可能依赖于libpthread,因此您可能需要更改编译器命令行,以便在libpthreads之后libthreadpool来避免链接问题:

gcc -I threadpool main.c -o server -L thread-pool -lthreadpool -lpthreads

实际上,首选选项是使用-pthread选项,以确保pthread库已正确链接,并且完成了线程支持所需的任何其他编译器配置({{1}的顺序}选项似乎并不重要):

-pthread

在任何目标文件之后列出库(例如gcc -pthread -I threadpool main.c -o server -L thread-pool -lthreadpool )也是一个好主意,而不是在它们之前。在某些系统上,它将双向工作;在所有已知系统上,在目标文件始终有效之后列出库。

答案 1 :(得分:2)

正如Michael Burr所说,.h文件的#include以及与库文件的链接是两种不同(但相关)的东西。

当您构建包含多个部分(例如多个.c源文件或库)的C程序时,该过程分两步完成。首先,各个源.c文件是编译的,即从C源转换为可执行机器指令的模块。然后程序所需的所有模块和库都链接,构建可执行文件。

静态动态链接之间的区别仅在链接完成时。从概念上讲它们是相同的,但静态链接(使用静态库)是事先完成的,形成一个可以在以后运行的可执行文件,并且在执行之前立即进行动态链接。

链接类型(静态或动态)根本不会影响编译步骤。

在编译单个源文件期间,编译器需要为库函数的调用生成代码。例如,如果一个库包含一个以double作为参数的函数f,并且源文件包含代码f(7),则编译器需要知道有一个名为f的函数,并且它期望一个double作为参数,因此编译器可以在实际调用函数f之前生成将整数7转换为double的代码。

这是通过将函数声明放在.h文件中完成的,该文件随后包含在.c源文件中。例如,该声明可能如下所示:

void f(double);

这使编译器能够生成正确的代码,并在出现错误时提供正确的警告和错误消息。

另一方面,库包含已编译的函数 definition ,它是执行某些操作的函数的实际代码。

请注意,编译步骤与库文件几乎没有关系,与静态或动态链接之间的区别无关。为了能够#include .h文件,编译器需要知道在哪里找到.h文件。这可能与实际的库文件完全不同。库文件甚至不必存在于同一台计算机上,甚至根本不存在。执行#include时,库中的实际函数可能尚未写入。

混淆的一个原因可能是gcc命令,

gcc -lpthreads main.c -o server -L thread-pool -lthreadpool

看起来它既执行编译又链接。它确实如此,但这只是为了方便,而且在幕后它仍然分两步完成。