GLAPIENTRY and variations

As part of the learning process I have been looking at the source-code for glTrace.
Many definitions use the word GLAPIENTRY as in :-

GLAPI void GLAPIENTRY glClearIndex( GLfloat c );

On my system (in gl.h) I can only find WINGDIAPI and APIENTRY as in :-

WINGDIAPI void APIENTRY glAccum (GLenum op, GLfloat value);

What on earth do these definitions mean and why the four variations (in bold type) ?

The only clue is in gl.h provided with glTrace (not the Microsoft gl.h) which states :-

if defined(_MSC_VER) && defined(BUILD_GL32) /* tag specify we’re building mesa as a DLL */

define GLAPI __declspec(dllexport)

elif defined(_MSC_VER) && defined(_DLL) /* tag specifying we’re building for DLL runtime support */

define GLAPI __declspec(dllimport)

else /* for use with static link lib build of Win32 edition only */

define GLAPI extern

endif /* _STATIC_MESA support */

define GLAPIENTRY __stdcall

#else
/* non-Windows compilation */

define GLAPI extern

define GLAPIENTRY

#endif /* WIN32 / CYGWIN bracket */

I have no idea what any of GLAPI, GLAPIENTRY, WINGDIAPI or APIENTRY mean .

David Sykes

WINGDIAPI is equal to GLAPI
APIENTRY is equal to GLAPIENTRY

WINGDIAPI and APIENTRY are Windows specific names, used/declared by the Windows include files (#include <windows.h> ). GLAPI and GLAPIENTRY were “invented” by Paul for Mesa (I believe), in order to support Windows without conflicting with Windows declared names, and without exporting ugly Windows names to non Windows platforms (correct me if I’m wrong), since Mesa supports multiple platforms.

The odd names hide some compiler and system specific declarations. These are basically only used under Windows (I have never seen these defined to anything on any other system). Basically they tell:

  1. This function is located in a DLL (WINGDIAPI / GLAPI)
  2. This function uses the MS “STDCALL” calling convention (APIENTRY / GLAPIENTRY)

Number one mostly has to do with function naming (how to find it in the DLL), and number two has to do with how arguments are passed on the stack.

…so basically (for MSVC, anyway):

#define WINGDIAPI __declspec(dllimport)
#define APIENTRY __stdcall

#define GLAPI WINGDIAPI
#define GLAPIENTRY APIENTRY

Reply rating poll: Did this reply make you any happier - or just more confused

On Apple’s sample code for glut : glsmap.h Mark Kilgard says :-

/* Try hard to avoid including <windows.h> to avoid name space pollution,
but Win32’s <GL/gl.h> needs APIENTRY and WINGDIAPI defined properly. */

In wingdi.h it states :-

// Define API decoration for direct importing of DLL references.
//

#if !defined(GDI32)
#define WINGDIAPI DECLSPEC_IMPORT
#else
#define WINGDIAPI
#endif

//

How do we know if GDI32 has been declared or not and surely this implies the header files would have to be read in a very specific order ?

Some parameters have leading underlines others have leading and trailing.
Is this a convention or a requirement ?

In the event GDI32 IS defined what does that imply for importing of DLL references ?

To quote MSDN, “using __declspec(dllimport) is better because [if] the linker does not generate a thunk if it is not required.”

In addition, in windef.h it states :-

#define APIENTRY WINAPI
#define WINAPI _stdcall

This all seems very convoluted but I guess there must be a reason for it :slight_smile:

Thanks for clarification.

It sounds as if you are worrying a bit too much

Why do you need to know exactly what is going on?

Anyway, when you write a function that is to be exported thorugh a DLL, you usually declare it as:

__declspec(dllexport) void _stdcall myFunction( void )
{
// …
}

When you want to call the function from a program, the prototype should look like this:

__declspec(dllimport) void _stdcall myFunction( void );

Notice how the __declspec(dllexport) changed to __declspec(dllimport).

Also notice how ugly these declarations look.

Also notice that the function “decorations” may differ from compiler to compiler.

Also notice that it you are NOT writing a DLL function (e.g. if you are writing a static link library, or if you are not even on a Windows platform), you would not have any special “decorations” at all:

void myFunction( void );

Because of these several different cases, and because of source code readability, you hide these declarations in macros/defines. In the case of MS Windows/Visual C++ OpenGL include files, WINGDIAPI (OpenGL is considered part of GDI, I believe) and APIENTRY, and in the case of MESA (and some other implementations/compiler includes) GLAPI and GLAPIENTRY.

Don’t worry too much about in which order Windows include files are included. You will end up with the above defines anyway.

I have done some hacking with these defines for the GLFW include file ( GLFW ), and for my tweaked OpenGL 1.4 include files ( here - click "GL includes" ), if you want to dive in…

Edit: Here is a quick link to the GLFW include file: glfw.h - it is hopefully better commented then the Mesa gl.h include file.

[This message has been edited by marcus256 (edited 04-22-2003).]

Thanks for the information, I will study it carefully.
At this learning stage it is difficult to know if we are getting over-concerned about the ‘trees’ rather than simply studying the ‘forest’.

Although not directly concerning OpenGL, can I ask a final question ?

Consider this function-declaration in a particular class :-

virtual MemArray* load(File& file) = 0;

Does this mean the ‘load’ function is not implemented in this class but can be defined in a derived class and must return a pointer to a MemArray object ?
The ‘load’ function takes a single parameter that is the address of a File object ?

I do not know what the final ‘= 0;’ means.

Thanks in advance.

The = 0 basically makes that a “pure virtual” function. That means that it is not implemented in the base class, and must be overridden by derived classes. You cannot create an instance of any class with a pure virtual method. You can only create an instance of the classes derived from such an object, which implement the pure virtual functions.