包含的 C++/C header 文件的实现在哪里?

Where is the implementation of included C++/C header files?

这可能看起来有点愚蠢:) 但它已经困扰了一段时间。当我在我的 C++/C 程序中包含一些其他人编写的 header 文件时,编译器如何知道 header 文件中声明的 class 成员函数的实现在哪里?

假设我想编写一些利用 OpenCV 库的程序。通常我想使用:

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

然而,这些只是 header 个文件,据我所知,这些文件只声明了函数而没有实现。那么编译器怎么知道去哪里找实现呢?特别是当我想构建一个.so文件时。

There is a similar post. 基本上它说 thrid-party 库,特别是。商业产品不发布源代码,所以他们发布了带有 header 的 lib 文件。但是,它并没有说明编译器如何知道在哪里可以找到 lib 文件。另外,那个post里的答案提到如果我想编译我自己的代码,我需要那些header文件的实现源代码。这是否意味着我无法在没有实现源的情况下构建 .so 文件?

确切的答案是特定于平台的,但总的来说,我会说一些库实际上只是头文件,而其他库在二进制目标文件中包含库方法的实现。我相信 OpenCV 属于第二种,即提供目标文件中的实现,用于动态或静态 linking,以及你的程序 links 反对它们。如果您的构建有效,那么它已经针对这些库配置为 link。在这一点上,细节变得非常特定于平台和构建系统。

请注意,对于 Windows、Mac 和 Linux 等常见平台,您很少需要自己构建像 OpenCV 这样的流行库。您提到了 .so 文件,这意味着在 Linux 上动态 linking。这个库是开源的,所以理论上你可以自己构建它,但实际上我更愿意使用我的发行版的包安装工具(例如 apt-get 或 yum)从我的发行版安装 opencv-dev(或类似的东西)存储库。

通常,实现预编译 库的形式分发。您需要告诉编译器它们所在的位置。

例如,对于 gcc,引用 online manual

-llibrary
-l library

Search the library named library when linking. [...]

并且,

-Ldir

Add directory dir to the list of directories to be searched for -l.


注意:您无需明确指定标准库,它们会自动链接。相反,如果您 不想 它们与您的二进制文件链接,您需要通过传递 -nostdlib 选项来通知编译器。

正如其他人已经解释的那样,您需要告诉编译器在哪里寻找文件。 这意味着您应该知道为您的编译器指定哪个路径。

某些组件提供了一种机制,您无需知道确切的路径,但可以自动从您的系统中检索它。

例如,如果您想使用 GTK+3 进行编译,则需要为您的编译器指定这些标志:

CFLAGS:= -I./ `pkg-config --cflags gtk+-3.0`

LIBS:= -lm `pkg-config --libs gtk+-3.0`

这将自动生成 GCC 所需的包含和库路径标志。

编译器工具链至少包含两个主要工具:编译器和link编辑器(将编译器整个链命名是很常见的,但严格来说是错误的)。

编译器负责从可用的源代码中生成 object 代码。在那个阶段,编译器知道在哪里定位标准 headers,并且可以被告知使用 non-standard 目录来定位 headers。例如,gcc 使用 -I 让您指定更多可能包含 headers.

的备用目录

link 编辑器负责从object 代码生成可执行文件(其基本常用用法)。要生成可执行文件,它需要在 compile-time 找到您未提供源代码的已声明事物的每个实现。这些可以是其他 object 代码,库中的 object 代码等。link 编辑器知道标准库的位置,可以告诉您让您指定 non-standard 目录。例如,您可以告诉 gcc 工具链使用带有 L 的备用目录,其中可能包含库。您可能知道 link 版本现在通常是一个两个阶段的过程:location-and-name-resolution 在 link-time 和真正的 link-edition 在 run-time(动态库很常见) .

基本上,库只是 collection 的 object 代码。查阅互联网,了解如何从 object 代码的源代码轻松构建库。