我试图将回调函数从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

最佳答案

如果仅这是您得到的错误,那是一条很糟糕的消息。这是调用约定的问题。

从我的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打在上面。

但是,正如阿里在下面的评论中指出的那样,将GLAPIENTRY拍到回调签名上并不总是可行。看来GLU 1.3 spec只是指定了void (*func)()被接受。由于某些实现需要一个_GLUfuncptr来代替,而GLAPIENTRY包括GLAPIENTRY的要求,但是其他实现根本没有定义GLAPIENTRY,因此这里存在可移植性问题。

可能的解决方法可能是:
#ifndef GLAPIENTRY
#define GLAPIENTRY
#endif

并使用ojit_code宏声明所有回调。

10-08 05:37