开发者

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开发者_如何学C 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜