8

我有一个我正在尝试修改的 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 在退出之前调用清理方法吗?

4

5 回答 5

10

如果你这样称呼,在 freeglut 中:

glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION)

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

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

于 2011-10-12T02:21:02.813 回答
4

我偶尔会为此而堕落,试图与 GLUT 一起玩。我尝试了所有我能做的事情,包括 IIRCglutMainLoop通过主函数中捕获的异常退出,但是......

使用时glutMainLoop

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

这个全局Context对象析构函数将在退出 main 后立即调用。

重要Context的是全局变量,而不是在主函数中声明的变量,因为我仍然无法理解的原因(我仍然看不到这种实现选择的兴趣),glutMainLoop 不会返回。

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

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

使用glutMainLoopEvent

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

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

glutMainLoopEvent只会解决挂起的事件,然后返回。for(;;)因此,您必须在对 的调用周围提供事件循环(构造) glutMainLoopEvent,但是这样,您可以使用 GLUT 并且仍然可以控制事件循环,并在需要时释放资源。

于 2010-04-22T15:46:13.357 回答
3

如果您使用的是 C/C++,也许您可​​以使用atexit()调用?

于 2010-04-22T04:00:12.117 回答
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 不会削减它。

于 2014-07-22T21:37:05.880 回答
0

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

于 2010-04-22T04:03:09.970 回答