错误:从'void(*)()'到'void(*)()'的转换无效 - 什么?

时间:2011-02-17 12:19:10

标签: c++ c opengl gcc function-pointers

我正在尝试将回调函数从C ++传递给OpenGL(C API):

gluQuadricCallback(qobj, GLU_ERROR, errorCallback);

其中errorCallback是编译为C ++代码的文件中的函数,并声明为

void errorCallback();

代码在Linux上用g ++ 4.4干净地编译,但在Windows上使用mingw32 g ++ 4.4会出现以下错误:

..\glwidget.cpp:172: error: invalid conversion from 'void (*)()' to 'void (*)()'

..\glwidget.cpp:172: error:   initializing argument 3 of 'void gluQuadricCallback(GLUquadric*, GLenum, void (*)())'

是某种C和C ++混合问题吗?我该如何解决这个问题?

更新: void GLAPIENTRY errorCallback(); 无法编译 :(
.. \ glwidget.cpp:129:错误:'errorCallback'之前的预期初始化程序 现在几乎可以肯定这是一个调用会议问题,与C链接无关,请参阅Thomas回答下面的评论。

更新2:在我看来,我遇到了一个关于GLAPIENTRYAPIENTRY_GLUfuncptr的凌乱的OpenGL问题。以下是关于可移植性问题的非常长的讨论:
http://lists.openscenegraph.org/pipermail/osg-users-openscenegraph.org/2007-October/003023.html

1 个答案:

答案 0 :(得分:7)

如果这是你得到的错误,那是一个非常糟糕的消息。这是调用约定的问题。

来自我的glu.h

GLAPI void GLAPIENTRY gluQuadricCallback (GLUquadric* quad, GLenum which, _GLUfuncptr CallBackFunc);

_GLUfuncptr定义为:

typedef void (GLAPIENTRYP _GLUfuncptr)();

#ifndef GLAPIENTRYP
#define GLAPIENTRYP GLAPIENTRY *
#endif

#ifndef GLAPIENTRY
#if defined(_MSC_VER) || defined(__MINGW32__)
#define GLAPIENTRY __stdcall
#else
#define GLAPIENTRY
#endif
#endif

这解释了Linux和mingw之间的区别。

由此,您认为需要将回调声明为

void GLAPIENTRY errorCallback();

并在适当时将__stdcall打到它上面。

但是,正如Ali在下面的评论中指出的那样,将GLAPIENTRY打到回调签名上并不总是有效。似乎GLU 1.3 spec只是指定接受void (*func)()。由于某些实现需要_GLUfuncptr而不是GLAPIENTRY要求,但其他实现根本没有定义GLAPIENTRY,因此这里存在可移植性问题。

可能的解决方法可能是:

#ifndef GLAPIENTRY
#define GLAPIENTRY
#endif

然后使用GLAPIENTRY宏声明所有回调。