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

Ali*_*Ali 6 c c++ opengl gcc function-pointers

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

gluQuadricCallback(qobj, GLU_ERROR, errorCallback);
Run Code Online (Sandbox Code Playgroud)

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

void errorCallback();
Run Code Online (Sandbox Code Playgroud)

代码在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 (*)())'
Run Code Online (Sandbox Code Playgroud)

是某种C和C++混合问题吗?我怎么解决这个问题?

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

更新2:在我看来,我正好碰上关于一个混乱的OpenGL的问题GLAPIENTRY,APIENTRY_GLUfuncptr.以下是关于可移植性问题的非常长的讨论:http:
//lists.openscenegraph.org/pipermail/osg-users-openscenegraph.org/2007-October/003023.html

Tho*_*mas 7

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

从我的glu.h:

GLAPI void GLAPIENTRY gluQuadricCallback (GLUquadric* quad, GLenum which, _GLUfuncptr CallBackFunc);
Run Code Online (Sandbox Code Playgroud)

_GLUfuncptr 定义为:

typedef void (GLAPIENTRYP _GLUfuncptr)();
Run Code Online (Sandbox Code Playgroud)

#ifndef GLAPIENTRYP
#define GLAPIENTRYP GLAPIENTRY *
#endif

#ifndef GLAPIENTRY
#if defined(_MSC_VER) || defined(__MINGW32__)
#define GLAPIENTRY __stdcall
#else
#define GLAPIENTRY
#endif
#endif
Run Code Online (Sandbox Code Playgroud)

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

从这开始,你认为你需要声明你的回调为

void GLAPIENTRY errorCallback();
Run Code Online (Sandbox Code Playgroud)

并且__stdcall将被掌掴到它在适当的时候.

但是,正如阿里在下面的评论中指出的那样,GLAPIENTRY对回调签名的打击并不总是有效.似乎GLU 1.3规范只是指定a void (*func)()被接受.由于某些实现需要_GLUfuncptr包含GLAPIENTRY需求的替代,但其他实现根本没有定义GLAPIENTRY,因此这里存在可移植性问题.

可能的解决方法可能是:

#ifndef GLAPIENTRY
#define GLAPIENTRY
#endif
Run Code Online (Sandbox Code Playgroud)

然后用GLAPIENTRY宏声明所有回调.