简体   繁体   中英

error: invalid conversion from 'void (*)()' to 'void (*)()' — what?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM