在面向对象程序中使用GLUT

时间:2012-01-16 00:39:04

标签: c++ opengl object linker glut

我正在用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。

4 个答案:

答案 0 :(得分:1)

如果你只是做UI的东西,而且没有原始绘图,那么Qt会更适合你吗?

http://qt.nokia.com/

答案 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框架可能是一个更好的主意。