我有一个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在退出之前调用一个清理方法?
答案 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都不会削减它。