I am trying to pass a callback function from C++ to OpenGL (C API):
gluQuadricCallback(qobj, GLU_ERROR, errorCallback);
where errorCallback
is a function in a file compiled as C++ code and is declared as
void errorCallback();
The code compiles cleanly with g++ 4.4 on Linux but gives the following error with mingw32 g++ 4.4 on Windows:
..\glwidget.cpp:172: error: invalid conversion from 'void (*)()' to 'void (*)()'
..\glwidget.cpp:172: error: initializing argument 3 of 'void gluQuadricCallback(GLUquadric*, GLenum, void (*)())'
Is it some sort of C and C++ mix problem? How can I solve this?
UPDATE: void GLAPIENTRY errorCallback();
doesn't compile either :(
..\glwidget.cpp:129: error: expected initializer before 'errorCallback'
Now it's almost sure it is a calling convention issue and has nothing to do with C linkage, see the comments below Thomas' answer.
UPDATE 2: It seems to me I just run into a messy OpenGL issue concerning GLAPIENTRY
, APIENTRY
and _GLUfuncptr
. Here is a VERY LONG discussion on portability issues:
http://lists.openscenegraph.org/pipermail/osg-users-openscenegraph.org/2007-October/003023.html
If that's all you're getting for an error, that's a pretty shitty message. This is an issue with calling conventions.
From my glu.h
:
GLAPI void GLAPIENTRY gluQuadricCallback (GLUquadric* quad, GLenum which, _GLUfuncptr CallBackFunc);
_GLUfuncptr
is defined as:
typedef void (GLAPIENTRYP _GLUfuncptr)();
with
#ifndef GLAPIENTRYP
#define GLAPIENTRYP GLAPIENTRY *
#endif
#ifndef GLAPIENTRY
#if defined(_MSC_VER) || defined(__MINGW32__)
#define GLAPIENTRY __stdcall
#else
#define GLAPIENTRY
#endif
#endif
That explains the difference between Linux and mingw.
From this, you'd think you need to declare your callback as
void GLAPIENTRY errorCallback();
and a __stdcall
will be slapped onto it when appropriate.
However, as Ali notes in the comments below, slapping GLAPIENTRY
onto the callback signature doesn't always work. It seems that the GLU 1.3 spec simply specifies that a void (*func)()
is accepted. Since some implementations require a _GLUfuncptr
instead, which includes the GLAPIENTRY
requirement, but others don't define GLAPIENTRY
at all, there is a portability problem here.
A possible workaround might be:
#ifndef GLAPIENTRY
#define GLAPIENTRY
#endif
and declare all callbacks with the GLAPIENTRY
macro nevertheless.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With