为何OpenGL库导出扩展符号?Linux下扩展符号使用与包装疑问
问题
我计划在Linux系统中基于NVIDIA驱动安装的libGL.so.1开发OpenGL库的包装器,发现该库导出了约3000个符号,其中多数为扩展符号。示例如下:
$ nm -D /usr/lib/x86_64-linux-gnu/libGL.so.1 ... 0000000000047400 T glBeginConditionalRender 0000000000047420 T glBeginConditionalRenderNV 0000000000047440 T glBeginConditionalRenderNVX 0000000000047460 T glBeginFragmentShaderATI 0000000000047480 T glBeginOcclusionQueryNV 00000000000474a0 T glBeginPerfMonitorAMD 00000000000474c0 T glBeginPerfQueryINTEL ...
我不清楚这些扩展符号的使用方式,想咨询:通常这类扩展符号应直接调用还是通过GetProcAddress()间接调用?若无需直接调用则无需对其进行包装。另外该情况是否也适用于glX的扩展符号?
回答
OpenGL扩展符号
- 不建议直接调用导出的扩展符号:NVIDIA的
libGL.so.1导出大量扩展符号是其驱动的特定行为,并非所有OpenGL实现(如Mesa、AMD驱动)都会这么做。直接链接这些符号会导致你的包装器在非NVIDIA环境下无法编译或运行,兼容性极差。 - 标准做法是通过
glGetProcAddress()间接调用:所有OpenGL扩展规范都要求通过该函数获取函数指针后再调用,这是跨平台、跨驱动的通用方式。你只需包装核心OpenGL函数,扩展函数无需提前包装,用户可通过你的包装器提供的glGetProcAddress()代理获取扩展函数指针。
glX扩展符号
glX扩展遵循完全相同的原则:
- 不要直接链接驱动导出的glX扩展符号(如
glXSomeExtensionFunctionARB),这类符号同样不具备跨驱动兼容性。 - 必须通过
glXGetProcAddress()获取glX扩展函数的指针后再调用,你的包装器只需处理标准glX核心函数,扩展函数交给用户通过动态获取的方式使用。
内容的提问来源于stack exchange,提问作者Chen Chen
相关产品推荐
相关产品推荐

