OpenGL头文件中的平台特定宏

3

我正在解析gl.h文件时,注意到OpenGL函数的声明方式非常不寻常(至少对我来说是这样)。以下是一个例子:

GLAPI void APIENTRY glEvalCoord1d( GLdouble u );
GLAPI void APIENTRY glEvalCoord1f( GLfloat u );
GLAPI void APIENTRY glEvalCoord1dv( const GLdouble *u );

很显然,这些都是返回类型为void的常规函数,但我的问题是关于GLAPI和APIENTRY宏的效果。这两个宏是特定于平台的,在头文件开头声明:
/* GLAPI, part 1 (use WINGDIAPI, if defined) */
#if defined(__WIN32__) && defined(WINGDIAPI)
#  define GLAPI WINGDIAPI
#endif

/* GLAPI, part 2 */
#if !defined(GLAPI)
#  if defined(_MSC_VER)                        /* Microsoft Visual C++ */
#    define GLAPI __declspec(dllimport)
#  elif defined(__LCC__) && defined(__WIN32__) /* LCC-Win32 */
#    define GLAPI __stdcall
#  else                                        /* Others (e.g. MinGW, Cygwin, non-win32) */
#    define GLAPI extern
#  endif
#endif

/* APIENTRY */
#if !defined(APIENTRY)
#  if defined(__WIN32__)
#    define APIENTRY __stdcall
#  else
#    define APIENTRY
#  endif
#endif

我希望制作一个代码解析器,能够浏览标题并列出其内容,所以我的问题是如何处理这些宏并对其进行转换。

我对C++还比较陌生,所以那些不规则的函数声明对我来说并不熟悉。我发现__declspec(dllimport)和__stdcall基本上是处理win32 api和DLL的MS东西,我知道"extern"的意思,但是在win32版本中,APIENTRY是__stdcall,这个我懂,但是另外一种情况似乎没有定义APIENTRY为任何东西,这是什么意思呢?

这两者之间有什么区别:

void glEvalCoord1d( GLdouble u );
__stdcall void __stdcall glEvalCoord1d( GLdouble u );

1
以上两者的区别仅在于 __stdcall,它控制使用的调用约定。创建的汇编代码以一种称为 stdcall 调用约定的方式执行函数调用。有关详细信息,请参阅此处。这是 Microsoft 的扩展,可以确保正确传递事物。是的,否则将其定义为空,这意味着在不需要它的平台上被省略。 - Nerdtron
所以基本上,所有这些宏代码(宏的复数形式是macro吗?)的结果,唯一的标准C++关键字是extern,其余的都是微软特定的东西,与C++无关,但是针对MS编译器? - dtech
基本上,是的。 - zerm
stdcall调用约定是一种标准的东西,MS扩展只提供了一个关键字,允许你强制使用该调用约定。 - Nerdtron
8
我希望你能翻译这句话:"I want to make a code parser that goes through headers and lists their content"。我的强烈建议是不要这样做。阅读用于生成OpenGL头文件的.spec文件比执行您正在执行的操作要容易得多。实际上,我已经有一些用于执行此操作的脚本,将OpenGL的定义收集到XML文件中以便更易处理。 - Nicol Bolas
除了Nicol Bolas的建议外,GLEW库还具有从GL规范生成头文件的脚本。 - Brett Hale
1个回答

1
你可以使用预处理器来完成这个任务,类似于这样:
gcc --nostdinc -E -DGLAPI="" -DAPIENTRY="" yourHeader.h > cleanedFile.h

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接