简介
我是一名经验丰富的程序员,拥有多年的面向对象范式经验。最近我决定尝试使用比C#或Java等语言更低级的语言更熟悉和舒适,所以我正在深入研究 C ,并尝试创建一些游戏用它。
一切进展顺利,现在我试图通过将函数定义移动到单独的.c文件中来更好地组织我的代码。这是我开始感到不舒服的地方,因为 C 中包含的性质。我非常熟悉它的工作原理,也非常熟悉编译期间的预处理阶段。问题是我仍然不确定我是否正确处理了这个问题。
我认为我的问题类似于被问到的here。虽然它不能完全满足我需要知道的东西。
问题
基本上,我正在使用两个库创建一个OpenGL项目。一个是 glew (对于OpenGL函数加载),另一个是 GLFW (用于窗口处理和OpenGL上下文创建)。我有两个.c文件,一个名为 main.c ,另一个名为 windowInitialize.c 。问题是, main.c 和 windowInitialize.c 都取决于glew和glfw库。
在我的 main.c 文件中,我执行以下操作包括:
#include "includes/GLEW/glew.h"
#include "includes/GLFW/glfw3.h"
#include "windowInitialize.h"
此外, main.c 执行以下相关函数调用:
if (!initializeGLFW())
return -1;
GLFWwindow *window = createOpenGLWindow(3, 3, 640, 480, "Hello OpenGL");
/* It is important that we initialize glew AFTER initializing GLFW and setting up
the OpenGL context, as GLEW needs a current context to work */
initializeGLEW();
windowInitialize.c 包括函数 initializeGLFW 和 initializeGLEW 的定义,以及 createOpenGLWindow 。 main.c 源仍然使用 glew 和 glfw 作为主循环目的,从两者中引用函数等。
现在, windowInitialize.c 包括:
#include "windowInitialize.h"
#include "includes/GLEW/glew.h"
#include "includes/GLFW/glfw3.h"
#include <stdio.h>
然后继续填写函数定义。这就是交易。如果glew和glfw库以及stdio实际上都需要使用这两个文件(用于打印调试消息等)。
我觉得这不是正确的做法,但我不确定。我相信编译器/链接器不抱怨双重声明的原因是因为main.c和windowInitialize.c获取了单独的目标代码文件。
我的问题是,链接器是否足够巧妙,只能将这些声明放在可执行文件中一次?即使我将这些标题包括在几个地方,它也不会对文件大小产生任何影响吗?这甚至是处理几个源文件之间的公共依赖关系的正确方法吗?或者我应该使用其他方法吗?
答案 0 :(得分:6)
你所描述的一切似乎都是正常的做事方式。您的两个编译单元只在这些头中获得相同的前向声明,而不是库中的实际重复定义。
我的问题是,链接器是否足够巧妙,只能将这些声明放在可执行文件中一次?
链接器当然不关心你包含的头文件 - 它是一个链接器,而不是编译器。
即使我将这些标题包含在几个地方,它也不会对文件大小产生任何影响吗?
函数的额外/未使用的前向声明对二进制大小没有影响。
这是否是处理多个源文件之间常见依赖关系的正确方法?
是的,你似乎是以完全正常的方式做事。
对于您的项目,您应该执行以下操作:
cc -c -o main.o main.c # compile main.c
cc -c -o windowInitialize.o windowInitialize.c # compile windowInitialize.c
cc -o myProgram main.o windowInitialize.o -lglew -lglfw # link objects with necessary libraries to create executable
但是,实际上,使用makefile会更好:
myProgram: main.o windowInitialize.o
cc -o $@ $^ -lglew -lglfw
使用它的例子:
$ make
cc -c -o main.o main.c
cc -c -o windowInitialize.o windowInitialize.c
cc -o myProgram main.o windowInitialize.o -lglew -lglfw
答案 1 :(得分:1)
链接器将仅使用您实际使用的库中的那些函数,它只执行一次。至于方法,在书中我正在阅读atm建议是制作一个包含所有库,函数声明,定义的文件,并且只包含一个文件,例如。 mydefinitions.h,而不是在项目的每个文件中单独执行。希望它有所帮助。