我正在用C ++为一个简单的问题域设置一个模拟器。底层函数编写在一个类MountainCar.cpp中,该类作为成员存储对GUI的引用,该GUI在另一个名为MCViewer.cpp的类中实现。我已经对GLUT有了不小的曝光度,所以我想而不是摸索替代品,我可以使用GLUT创建一个简单的GUI。问题是我可能一次运行多个模拟,我希望每个实例都有自己的GUI。这可能是常识,但GLUT是一个C API,我需要的某些调用如glutDisplayFunc和glutReshapeFunc需要指向C函数作为参数的指针。同时我需要传递的函数的行为依赖于一些任意的MCViewer对象实例。
我发现了一个有用的thread here on stackoverflow,它建议创建并传递全局回调函数,同时在MCViewer类中实现相应的被调用函数。由于回调函数是全局的但是打算在某个指定的对象实例上运行,因此需要另一个存储对某些当前MCViewer对象的引用的全局变量。
结果标题:
#ifndef MCVIEWER_H__
#define MCVIEWER_H__
#include <cstdlib>
#include <ctime>
#include <stdlib.h>
#include <string>
#include <math.h>
#include <iostream>
#include <assert.h>
#include <GLUT/GLUT.h>
class MCViewer {
//MCViewer declarations, implementation specified in corresponding .cpp
};
extern MCViewer *currRef;
extern "C" {
static void displayFcnCB(void) {
currRef->displayFcn();
}
static void winReshapeFcnCB(GLint newWidth, GLint newHeight) {
currRef->winReshapeFcn(newWidth, newHeight);
}
static void keyboardActionCB(GLubyte key, GLint xMouse, GLint yMouse) {
currRef->keyboardAction(key, xMouse, yMouse);
}
}
#endif //MCVIEWER_H__
问题源于在MCViewer.cpp和MountainCar.h文件中包含此文件。回想一下,根据我的设计,MountainCar对象应该存储对其指定GUI的引用。在我将全局函数设为静态并标记全局变量currRef extern之前,我最初在链接期间遇到“重复”错误。现在我收到一些奇怪的错误,说明从MCViewer.o和MountainCar.o引用了currRef。
答案 0 :(得分:1)
如果你只是做UI的东西,而且没有原始绘图,那么Qt会更适合你吗?
答案 1 :(得分:1)
但OpenGL是一个C API,我需要的某些调用如glutDisplayFunc和glutReshapeFunc需要指向C函数的指针作为参数
所以? GLUT不是OpenGL的一部分,它只是一些第三方框架。你可以,事实上不应该使用GLUT来做任何复杂的事情。
答案 2 :(得分:1)
您可以在窗口标识符和GUI对象之间创建全局映射,并使用glutGetWindow
在全局显示或重塑函数中获取当前窗口ID。
答案 3 :(得分:0)
我可以使用GLUT创建一个简单的GUI。
如果你想要GUI,那么我建议使用别的东西。 Qt初始化OpenGL,并为跨平台开发提供强大的框架。没有充分的理由(我能想到)将GLUT用于多窗口应用程序。
extern MCViewer *currRef;
extern "C" {
static void displayFcnCB(void) {
currRef->displayFcn();
}
如果您不再尝试在标题内执行所有操作,那么您将避免很多麻烦。
非成员函数的在我将全局函数设为静态并标记全局变量currRef extern之前,我最初在链接期间遇到“重复”错误。
static关键字表示函数在一个* .cpp文件中可见,并且链接器不可见。由于您将静态函数(位于任何类之外)包含在标题中,因此您可能会遇到问题。删除static关键字,将函数体放入* .cpp文件,并将声明转发到标头中。或者保持静止并将其投入课堂。或保持静态非成员函数,但从标题中删除任何提及该函数。此外,您不需要使用extern "C"
。
需要另一个存储对某些当前MCViewer对象的引用的全局变量。
有glutGetCurrentWindow
函数应该返回当前窗口的ID。不要尝试通过全局变量传递函数参数,而是使用map(std::map
或类似的) - 将窗口ID映射到“viewer”类指针。试图通过全局变量传递函数参数是一种非常糟糕的编程习惯,这将使您的代码无法维护。
但是,此时,删除GLUT并使用不同的GUI框架可能是一个更好的主意。