OpenGL编译报typedef重定义(GL与Khronos类型冲突)如何解决
这是64位Linux平台编译OpenGL项目的典型类型冲突问题:GL/glx.h会递归引入系统自带的GL/glext.h,这个头文件会提前定义GLint64、GLuint64、GLintptr、GLsizeiptr四个标准OpenGL类型。
项目自带的openGLTypes.h是按Windows平台的类型规则写的自定义类型:Windows 64位环境下long占4字节,64位整数用long long,指针长度类型用32位int;但Linux 64位环境下long占8字节,系统GL头选long做这几个类型的底层基础类型。哪怕两边类型实际内存占用完全一致,编译器只要检测到typedef对应的基础类型名不同,就会报重定义错误。
另外原项目把GLintptr/GLsizeiptr定义为int32本身在64位环境下就是错误写法,这两个类型用来存指针地址偏移,长度必须和系统指针长度一致,64位系统下必须是8字节,原写法存在内存截断的潜在bug。
方案1:条件编译适配平台类型(最小改动,无连锁报错,推荐)
直接修改src/headers/openGLTypes.h的冲突类型定义,通过条件编译判断平台,和系统头文件的类型定义保持一致,改动量极小,不会触发其他编译错误:
- 定位到文件中报错的39、45、53、54行附近的四个类型typedef代码
- 用如下条件编译逻辑替换原有硬编码的类型定义:
// 保留原有其他代码,仅替换四个冲突类型的定义部分 // 64位整数类型适配 #if defined(__x86_64__) || defined(__aarch64__) typedef long GLint64; typedef unsigned long GLuint64; typedef long GLintptr; typedef long GLsizeiptr; #else // 32位环境保留原项目的定义逻辑 typedef long long int64; typedef int64 GLint64; typedef unsigned long long uint64; typedef uint64 GLuint64; typedef int int32; typedef int32 GLintptr; typedef int32 GLsizeiptr; #endif
- 修改完成后直接清理构建缓存重新编译即可。
方案2:阻止glx.h递归引入glext.h(不想改类型定义可选)
如果不想调整原有类型定义,可以在openGLTypes.h的最顶部、所有头文件引入语句之前,加一个宏定义,阻止系统GL头自动引入glext.h:
// 必须放在#include <GL/glx.h>之前才生效 #define GL_GLEXT_LEGACY #include <GL/glx.h> // 后续保留原文件的所有代码不变
这个宏是系统GL头文件内置的控制开关,定义后glx.h不会递归加载glext.h,自然不会出现提前定义类型导致的重定义冲突。
不要直接把glx.h替换为glew.h:这个项目本身实现了手写的OpenGL函数指针加载逻辑,没有集成GLEW的初始化流程,直接替换头文件会触发全量函数声明重复、类型不匹配等连锁错误,会出现上千个编译报错,完全没有必要。
内容的提问来源于stack exchange,提问作者masterBroesel

