我有这些模块
sum_module.h
int sum(int x, int y);
tim_module.h
int tim(int x, int y);
我想创建一个名为myModule.lib的模块,该模块允许我在主程序中使用这些功能。想法是将myModule.lib添加到主项目中,并包含myModule.h
我的问题是:创建库(myModule.lib)时,它是否包含main.c和main.h?如果是,main.h是否等于myModule.h?我应该在main.c中放入什么?
答案 0 :(得分:6)
您的静态库是一组服务,因此它带有一个头文件,该头文件包含要向外部公开的功能的原型。如果您在此处没有放置main
符号,那么没有人会幸运地为您放置一个符号。
(请注意,文件名无关,它是与 symbol 相关的名称:main
)
从技术上讲,可以在其中放入main
(某些构建工具会创建一个.a
文件并与运行时链接以创建可执行文件),但是作为服务库,这会与任何尝试与其链接的应用程序,该应用程序还具有main
。
因此,请从您的库中删除我们所知道的main
函数(著名的int main(int argc, char**argv)
)(可以根据需要添加selftest
入口点)。创建静态库不涉及任何链接,创建动态库不需要main
,只需完整的符号解析和入口点即可。
答案 1 :(得分:3)
要回答您的问题,可能有必要了解从源代码编译和链接C程序的基本含义是什么,以及库如何发挥作用。
编译源文件将创建一个目标文件,您可以将其想象为“结构化机器代码”。它的结构在于它包含符号-命名变量和命名函数。这些符号实质上是标记为内存的地址,其中包含可以从其他代码读取或跳转到的数据或机器指令(即功能)。
nm和objdump之类的工具可用于检查目标文件并列出这些符号。
产生一个可运行的,静态链接的程序包括两个已知步骤,即编译(从源文件生成目标文件)和链接(将目标文件“粘合”在一起并执行一些魔术操作以生成一个可运行的实体)。 1 链接器通过计算要跳转到的最终程序中的数字地址来“解析”对其他目标文件中函数的调用。如果找不到这样的函数,则在逻辑上会出现“未定义符号”错误。
一个简单的静态库现在实际上只是对象文件及其包含的符号索引的连接。就这么简单。换句话说,您无需调用ld -o output /lib/crt0.o hello.o sum.o tim.o -lc
来链接(使用来自sum.c
和tim.c
的较早版本的目标文件),而是调用存档器ar
来生成静态库my_module.a
中包含以下两个目标文件:ar rcs my_module.a sum.o tim.o
然后在链接阶段,您将使用该库代替两个目标文件:ld -o output /lib/crt0.o hello.o my_modules.a -lc
将解析对sum
和tim
中的hello.o
,带有该库中的符号。
那么您的图书馆中需要一个main
吗?不,你为什么呢?您在该库中需要一个main
,而不是在sum.c
或tim.c
中需要一个{{我们假设您在main
中有一个hello.c
)。会痛吗?可能链接器抱怨“重复的符号”,因为它们无法告诉它们哪个是预期的符号。许多链接器提供了一个忽略该错误并使用遇到的第一个符号的选项,但是通常,这只是解决方法,直到构建过程干净为止。
gcc
,或者通过制作文件或IDE。一段时间以来,我实际上并未“手动”调用链接器ld
。但是这里的目的是让您对过程有所了解,因为这将使您能够回答自己的问题。