我目前正在玩弄C语言库NanoVG。该库依赖于OpenGL函数,并有2个头文件nanovg.h
和nanovg_gl.h
,后者包含部分实现。为了方便,我已将这两个头文件放在/usr/include/nanovg
中。
但是,当我尝试将以下代码编译成对象文件时,gcc没有抱怨:
// working.c
#include <GL/gl.h>
#include <nanovg/nanovg.h>
#define NANOVG_GL3_IMPLEMENTATION
#include <nanovg/nanovg_gl.h>
(命令:gcc -c working.c -o working.o
)
现在,我将头文件从/usr/include/nanovg/
复制到工作目录,并用以下代码替换:
// notworking.c
#include <GL/gl.h>
#include "nanovg.h"
#define NANOVG_GL3_IMPLEMENTATION
#include "nanovg_gl.h"
(命令: gcc -c notworking.c -o notworking.o
)
Gcc现在抱怨一些OpenGL函数没有声明:
... (many more similar complaints)
src/nanovg_gl.h: In function ‘glnvg__renderDelete’:
src/nanovg_gl.h:1540:3: warning: implicit declaration of function ‘glDeleteBuffers’; did you mean ‘glSelectBuffer’? [-Wimplicit-function-declaration]
1540 | glDeleteBuffers(1, &gl->fragBuf);
| ^~~~~~~~~~~~~~~
...
为什么一个文件可以顺利编译,而另一个文件却不行?
更深入一点:
使用cpp
工具,我发现这两个预处理文件之间的差异仅限于 # 指令,但就“C内容”而言,我没有看到任何区别。下面是working.c
的预处理片段。如果我从notworking.c
的预处理文件中添加#行,则gcc将不再编译预处理的working.c
并抱怨缺少对glDeleteBuffers
的声明。
// ...
if (gl ==
// # 1533 "src/nanovg_gl.h" 3 4 // <- uncomment this line and glDeleteBuffers is considered missing by gcc
((void *)0)
// # 1533 "src/nanovg_gl.h" // <- idem
) return;
glnvg__deleteShader(&gl->shader);
if (gl->fragBuf != 0)
glDeleteBuffers(1, &gl->fragBuf); // <- the function that gcc complains about is here
// ...
编辑: 为确保我没有做任何可能导致差异的卑鄙行径,我遵循了以下步骤,这些步骤希望在另一台计算机上可复现:
- GCC版本:
gcc (Ubuntu 10.3.0-1ubuntu1) 10.3.0
- 将此处找到的
GL/gl.h
版本复制到工作目录并将其命名为glfoo.h
- 将
nanovg
的头文件(如存储在仓库中)复制到/usr/include/nanovg/
和nanovg/
中(相对于工作目录)。 - 在工作目录中将以下内容保存为
test.c
:
#include "glfoo.h"
#include <nanovg/nanovg.h>
#define NANOVG_GL3_IMPLEMENTATION
#include <nanovg/nanovg_gl.h>
- 运行
gcc -c test.c -o test.o
=> 编译成功 - 将第2和第4行中的<...>替换为“..”,然后运行命令 => 编译失败。
我刚尝试了这些步骤,能够重现该问题。
nanovg
复制到您的工作目录中,并将其用作"nanovg/nanovg.h"
?你确定这些头文件是独立的,不依赖于其他任何内容吗? - ZosoglDeleteBuffers
。我对OpenGL一无所知,但似乎有些版本有这个函数,而有些则没有。例如,这个没有声明它(但它确实声明了建议使用的glSelectBuffer
)。然而,我不知道为什么从<...>
改为"..."
会导致包含不同版本的GL/gl.h文件。我的猜测(奥卡姆剃刀原理也表明)是你改变的不止这一个东西。 - Cliffordnanovg.h
不包含任何#include
语句,因此我认为它不依赖于其他任何内容。@Clifford:确实,我的GL/gl.h
没有声明glDeleteBuffers
,但我真的很好奇为什么在一种情况下会有影响而在另一种情况下则没有。包括GL/glext.h
并没有帮助,但是使用GL/glew.h
(在GL/gl.h
之前)错误确实消失了。 - Ahmad Bnotworking.c
不工作,而是为什么working.c
实际上可以工作,因为glDeleteBuffers
不应该在gl.h
中,也不在glext.h
中(除非你#define GL_GLEXT_PROTOTYPES
,但你绝对不应该这样做)。你必须始终使用像 GLEW 或 glad 这样的 GL 加载器来访问 GL 1.1 以上的每个函数。而 nanovg 源代码实际上希望你使用一个加载器,该加载器直接提供 GL 符号,或者使用一些预处理宏来重新定义它们(就像大多数加载器所做的那样)。 - derhass