退出OpenGL应用程序时清理

时间:2010-04-22 03:43:09

标签: c++ macos opengl glut

我有一个OSX OpenGL应用程序,我正在尝试修改。当我创建一个完整的应用程序 调用一堆初始化函数 - 包括我可以指定自己的鼠标和键盘处理程序等的方法。例如:

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(700, 700);
glutCreateWindow("Map Abstraction");
glutReshapeFunc(resizeWindow);
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutMouseFunc(mousePressedButton);
glutMotionFunc(mouseMovedButton);
glutKeyboardFunc(keyPressed);

在某些时候,我将控制传递给glutMainLoop并运行我的应用程序。在运行过程中,我创建了一大堆对象。我想清理它们。有没有什么办法可以告诉GLUT在退出之前调用一个清理方法?

5 个答案:

答案 0 :(得分:10)

如果你打电话给freeglut:

glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION)

在进入主循环之前,当窗口关闭时,主循环功能将返回,您可以进行清理。

值得注意的是,在那个阶段,GL上下文已被破坏,因此您无法执行任何GL操作。

答案 1 :(得分:4)

我偶尔摔倒了,试着玩GLUT。我尝试了所有我能做到的事情,包括IIRC通过主函数中的异常退出glutMainLoop但是......

使用glutMainLoop

我的解决方案如下:创建一个全局Context对象,该对象将是您所有资源的所有者,并在析构函数中释放这些资源。

退出main后,将立即调用此全局Context对象析构函数。

重要Context是一个全局变量,而不是在main函数中声明的变量,因为有一个原因仍然让我失望(我仍然没有看到这个实现选择的兴趣),glutMainLoop赢了不回来。

在我的Linux机器(Ubuntu)中,正确调用了析构函数。我想它也应该在Windows和MacOS上以相同的方式工作。

请注意,这是Francisco Soto的atexit()解决方案的C ++版本,没有可能的限制。

使用glutMainLoopEvent

显然,有些实现有一个glutMainLoopEvent,可以用来代替调用glutMainLoop。

http://openglut.sourceforge.net/group__mainloop.html#ga1

glutMainLoopEvent将仅解决待处理事件,然后返回。因此,您必须围绕调用for(;;)提供事件循环(glutMainLoopEvent构造),但这样,您可以使用GLUT并仍然可以控制事件循环,并释放您的资源需要时。

答案 2 :(得分:3)

如果您使用的是C / C ++,可以使用atexit()电话吗?

答案 3 :(得分:0)

通常你不需要这样做;退出应用程序将删除您分配的任何资源。即使您已经捕获了屏幕,它也应该恢复正常。

答案 4 :(得分:0)

我最后使用了paercebal的答案,以及之前尝试在glutMainLoop()周围使用try / catch块。为什么?因为我想要无论如何关闭都要正确清理。如果应用程序完全退出,则全局Context对象将被正确销毁,如果您通过关闭窗口(或在OS X上退出应用程序)关闭应用程序,会发生这种情况。但是如果你在启动它的终端点击ctrl-C(或发送一个SIGINT),清理就不会发生。为了解决这个问题,我在代码中添加了以下内容:

static bool exitFlag = false;

static void sighandler(int sig) {
  exitFlag = true;
}

static void idleFunc() {
  if(exitFlag) {
    throw NULL;
  }
}

然后在main()中:

signal(SIGINT, sighandler);
glutIdleFunc(idleFunc);

try {
  glutMainLoop();
} catch(...) {}

这不是最漂亮的代码,但它确实处理了正确退出程序的两种情况。

一个捕获(没有双关语) - 如果关闭窗口/正常退出应用程序,则不会调用catch()块之后放置的任何代码。您必须将清理代码放在全局Context对象中,如paercebal的答案所示。所有这些代码都是允许使用SIGINT信号离开glutMainLoop()。

我认为这里真正的教训是,对于任何非常复杂的事情,GLUT都不会削减它。

相关问题