我正在阅读一篇关于 C++ 库和静态/动态库和链接的文章。 我的问题如下:
1) 我们必须编译要插入库的文件,然后使用命令 ar -crsv 来创建库文件? (存档必须以 lib 开头并以 .a 结尾吗?)
2) g++的-I和-L命令用了一次?向编译器“说”库在哪里?还是每次编译使用库的源代码?
3) 必须使用#include<> 包含 Libray?如果是,名字是什么?
我不太明白静态库和静态链接是什么意思,动态链接是什么意思? 我所理解的是,使用静态库和链接时,我们将程序与库合并,这样就不需要原始位置的原始程序了? 对于 Dynamic,我所知道的是代表动态链接库的 DDl。那么对于这个DDL我能想到的唯一区别就是加载到主存中,但是我很困惑
任何有知识的人都可以将我的 - 可能是错误的 - 知识按正确顺序排列并解释更多这些条款吗?
谢谢!
最佳答案
假设您的代码是一个名为 main.cpp 的文件,如下所示:
#include<headerFromSomeLibrary>
#include<headerFromSomeOtherLibrary>
int main()
{
int var = functionFromTheLibrary();
int otherVar = functionFromTheOtherLibrary();
return var + otherVar;
}
编译将分两步进行。
首先,您将使用如下命令将main.cpp 编译成目标文件:
g++ -o main.o -c main.cpp -IheaderDirectory
其中 main.o 是将生成的目标文件的名称,headerDirectory 是包含 中包含的头文件的目录的路径main.cpp.
为了能够检查您的语法是否正确,编译器需要知道在 main.cpp 中调用但未在那里定义的类和函数看起来像什么(在此在这种情况下,那些来自库,但如果它们由您在另一个文件中定义,它的工作原理是一样的。
这就是 #include 指令的用武之地:它们指向包含所调用函数声明的 header ,并允许编译器执行其工作。如果声明位于名为 headerFromSomeLibrary.h 的头文件中,则相应的指令将是:
#include<headerFromeSomeLibrary>
此时,生成的文件 (main.o) 包含 main.cpp 中定义的函数的低级版本(在这种情况下只有 main() ).它还包含许多符号,允许识别在 main.cpp 中定义并由 main.cpp 调用的函数。
第二步是链接步骤。链接命令将如下所示:
g++ -o myProgram main.o -LsomeDirectory -lsomelibrary -lsomeotherlibrary
myProgram 是您要给可执行文件的名称,headerDirectory 是包含头文件的目录路径,someDirectory是包含 libsomeLibrary.a 和 libsomeOtherLibrary.a(您正在使用的库的二进制文件)的目录的路径。
与 main.o 类似,libsomelibrary.a 和 libsomeotherlibrary.a 包含函数的定义(即那些在 < em>main()),以及标识它们的符号。链接步骤的作用是使用符号将函数定义连接到函数调用。
如果库中的函数在文件 myfunctions.h 中声明并在 myfunctions.cpp 中定义,编译指令将如下所示:
g++ -o main.o -c main.cpp
g++ -o myfunctions.o -c myfunctions.cpp
g++ -o myProgram main.o myfunctions.o
基本上,-I 选项用于告诉编译器缺少的 header 在哪里,-l 选项告诉它缺少的二进制文件的名称,-L 选项告诉它在哪里可以找到这些二进制文件。这些选项不会从一次 g++ 调用到下一次调用“停留”(这没有意义)。
现在,您询问了静态链接和动态链接之间的区别。我上面解释的实际上是静态(即编译时)链接。在静态链接的情况下,编译器将在库中获取它需要的函数定义,并将它们添加到最终的可执行文件中。这很好,因为您的可执行文件不需要任何其他东西即可工作,并且因为您的编译器将能够在获取函数后进行优化。
但是,这并不总是您想要做的。一些库被许多不同的程序使用,您可以通过在程序之间共享库来节省大量空间。这就是动态(即运行时)链接的情况。在这种情况下,程序将在需要时简单地获取库。
关于C++ 库,静态和动态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23815769/