我正在尝试将回调函数从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:在我看来,我遇到了一个关于GLAPIENTRY
,APIENTRY
和_GLUfuncptr
的凌乱的OpenGL问题。以下是关于可移植性问题的非常长的讨论:
http://lists.openscenegraph.org/pipermail/osg-users-openscenegraph.org/2007-October/003023.html
答案 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
宏声明所有回调。