这可能看起来有点愚蠢:)但它已经困扰了一段时间。当我在C ++ / C程序中包含一些由其他人编写的头文件时,编译器如何知道头文件中声明的类成员函数的实现在哪里?
说我想写一些利用OpenCV库的程序。通常我会想要使用:
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
但是,这些只是头文件,据我所知,它只声明函数但没有实现。然后编译器如何知道在哪里找到实现?特别是当我想构建.so文件时。
There is a similar post.基本上它说第三方库,尤其是商业产品不发布源代码,因此他们将lib文件与头文件一起发送。但是,它没有说清楚编译器如何知道在哪里找到lib文件。另外,那个帖子中的答案提到如果我想编译自己的代码,我需要这些头文件的执行源代码。这是否意味着我无法在没有实现源的情况下构建.so文件?
答案 0 :(得分:5)
通常,实现以预编译库的形式分发。您需要告诉编译器它们的位置。
例如,对于gcc
,引用online manual
-llibrary -l library
链接时搜索名为 library 的库。 [...]
和
-Ldir
将目录 dir 添加到要搜索
-l
的目录列表中。
注意:您不需要显式指定标准库,它们会自动链接。相反,如果不希望将它们与二进制文件链接,则需要通过传递-nostdlib
选项来通知编译器。
答案 1 :(得分:0)
确切的答案是特定于平台的,但一般来说我会说某些库实际上只是头文件,其他库包括在二进制目标文件中实现库的方法。我相信OpenCV属于第二种类型,即提供目标文件中的实现,用于动态或静态链接,并且您的程序链接它们。如果您的构建有效,那么它已经配置为链接这些库。在这一点上,细节变得非常平台和特定于构建系统。
请注意,对于Windows,Mac和Linux等常见平台,您很少需要自己构建像OpenCV这样的流行库。你提到过.so文件,这意味着Linux上的动态链接。这个库是开源的,所以理论上你可以自己构建它,但实际上我宁愿使用我的发行版的软件包安装工具(例如apt-get或yum)从我的发行版中安装opencv-dev(或类似的东西)库中。
答案 2 :(得分:0)
正如其他人已经解释的那样,您需要告诉编译器在哪里查找文件。 这意味着您应该知道为编译器指定的路径。
某些组件提供了一种机制,您无需知道完全路径,但可以自动从系统中检索它。
例如,如果要使用GTK + 3进行编译,则需要为编译器指定这些标志:
CFLAGS:= -I ./`pkg-config --cflags gtk + -3.0`
LIBS:= -lm`pkg-config --libs gtk + -3.0`
这将自动生成GCC所需的包含和库路径标记。
答案 3 :(得分:-1)
编译器工具链至少包含两个主要工具:编译器和链接编辑器(将编译器命名为整个链很常见,但严格来说这是错误的。)
编译器负责从可用的源代码生成目标代码。在该阶段,编译器知道在何处定位标准头,并且可以被告知使用非标准目录来定位头。例如,gcc
使用-I
来指定一些可能包含标题的备用目录。
链接编辑器负责从目标代码生成可执行文件(其基本常见用法)。要生成可执行文件,它需要在编译时找到所声明事物的每个实现,而您没有提供源代码。这些可以是其他目标代码,库中的目标代码等。链接编辑器知道标准库的位置,并且可以告诉您指定非标准目录。例如,您可以告诉gcc
工具链使用可能包含库的L
的备用目录。您可能知道链接版本现在通常是一个两阶段过程:链接时的位置和名称解析以及运行时的实际链接版本(动态库非常常见)。
基本上,库只是对象代码的集合。请咨询互联网,了解如何从目标代码的源代码轻松构建库。