这可能是一个完全没有问题的问题,但在考虑在iOS中链接库时,我脑海中缺少链接。我通常只是添加一个已经交叉编译的新库,并设置构建和链接器路径,而不知道我在做什么。我希望有人可以帮助我填补一些空白。
我们以OpenCV库为例。我有这个完全正常工作因为一个写得很好的教程(http://niw.at/articles/2009/03/14/using-opencv-on-iphone/en),但我只是想知道究竟发生了什么。
我正在考虑的是,当我为iOS构建OpenCV时,您的创建对象代码将被放置在.a文件中。这个目标代码只是编译的实现文件(.m)。您希望这样做的一个原因是难以查看源代码,因此您不必每次都编译该源代码。
.h文件不会放在库中(.a)。在源文件中包含.h,这些头文件以某种方式与目标代码库(.a)进行通信。
您还必须在构建路径中包含库的头文件,并在链接器路径中包含库本身。
那么,我查看链接库的方式是否正确?如果,有人不能纠正我吗?
答案 0 :(得分:1)
基本上,你是对的。
编译库的源代码会为每个源文件生成一个目标文件(如果针对不同的体系结构进行多次编译,则会生成多个目标文件)。然后将所有目标文件存档(或打包)到一个.a文件(或Windows上的.lib)中。在此阶段,代码尚未链接。
.h文件为库提供的功能提供了一个接口。它们包含常量,函数原型,可能的全局声明(例如extern int bad_global;
)等等 - 基本上,编译使用库的代码所需的一切。
.h文件不以任何方式与目标代码“通信”。它们只是为编译器提供线索。考虑这个头文件:
// library.h
extern int bad_global;
int public_func(int, const void*);
通过在自己的代码中包含此文件,您只需告诉编译器将这些声明复制并粘贴到源文件中。您可以为OpenCV库编写声明,而不使用随其提供的标头。换句话说,你要求编译器不要发出有关未定义符号的错误,说“我在其他地方有这些符号,好吗?这是他们的声明,现在让我独自一人!”。
头文件需要包含在搜索路径中,以便编译器找到它们。您可以简单地通过完整路径包含它们,例如#include "path/to/file.h"
,或为您的编译器提供-I
选项,告诉他在哪里查找其他标头,然后使用#include <file.h>
。
编译代码时,头文件中的声明用作指示代码正在使用的符号在某处定义。请注意单词声明和定义之间的区别。头文件大多数时间只包含声明。
现在,在编译代码时,必须将其链接以生成最终的可执行文件。这是存储在库中的实际目标代码发挥作用的地方。链接器将查看目标代码中的每个符号,函数调用等,然后尝试为每个此类符号查找相应的定义。如果它在程序的目标代码中找不到它,它将看起来是标准库以及您提供它的任何其他库。
因此,重要的是要理解编译和链接是两个独立的阶段。您可以编写任何函数原型并在代码中使用它们,它将完全编译。但是,当涉及到链接阶段时,您必须为代码中使用的符号提供实现,否则您将无法获得可执行文件。
希望有意义!
答案 1 :(得分:0)
.a
是代码的编译版本。
库提供的头文件是其公共接口。它们显示了可用的类,方法和属性。它们不与二进制代码“通信”。
编译器需要标头知道在其他地方定义了符号(例如方法名称)。它们在“链接”步骤之后与库二进制文件中的右侧“代码段”相关联。