Added the ugly ATEXIT_HACK from GLUT 3.7, making freeglut binary compatible with...
authorSven Panne <sven.panne@aedion.de>
Fri, 22 May 2009 15:20:03 +0000 (15:20 +0000)
committerSven Panne <sven.panne@aedion.de>
Fri, 22 May 2009 15:20:03 +0000 (15:20 +0000)
git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@818 7f0cb862-5218-0410-a997-914c9d46530a

ChangeLog
include/GL/freeglut_std.h
src/freeglut_init.c
src/freeglut_internal.h
src/freeglut_menu.c
src/freeglut_window.c
src/freeglutdll.def

index 3dbb4d9..e6a6c3e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,8 @@
 2009-05-22  Sven Panne  <sven.panne@aedion.de>
+       * include/GL/freeglut_std.h,src/freeglut_init.c,src/freeglut_internal.h,
+         src/freeglut_menu.c,src/freeglut_window.c,src/freeglutdll.def: Added the
+         ugly ATEXIT_HACK from GLUT 3.7, making freeglut binary compatible with the
+         GLUT DLLs out in the wild.
 
        * src/freeglutdll.def: Removed obsolete lines. Fixed version number.
 
index f799233..3248929 100644 (file)
@@ -574,6 +574,45 @@ FGAPI void    FGAPIENTRY glutForceJoystickFunc( void );
 FGAPI int     FGAPIENTRY glutExtensionSupported( const char* extension );
 FGAPI void    FGAPIENTRY glutReportErrors( void );
 
+/* Comment from glut.h of classic GLUT:
+
+   Win32 has an annoying issue where there are multiple C run-time
+   libraries (CRTs).  If the executable is linked with a different CRT
+   from the GLUT DLL, the GLUT DLL will not share the same CRT static
+   data seen by the executable.  In particular, atexit callbacks registered
+   in the executable will not be called if GLUT calls its (different)
+   exit routine).  GLUT is typically built with the
+   "/MD" option (the CRT with multithreading DLL support), but the Visual
+   C++ linker default is "/ML" (the single threaded CRT).
+
+   One workaround to this issue is requiring users to always link with
+   the same CRT as GLUT is compiled with.  That requires users supply a
+   non-standard option.  GLUT 3.7 has its own built-in workaround where
+   the executable's "exit" function pointer is covertly passed to GLUT.
+   GLUT then calls the executable's exit function pointer to ensure that
+   any "atexit" calls registered by the application are called if GLUT
+   needs to exit.
+
+   Note that the __glut*WithExit routines should NEVER be called directly.
+   To avoid the atexit workaround, #define GLUT_DISABLE_ATEXIT_HACK. */
+
+/* to get the prototype for exit() */
+#include <stdlib.h>
+
+#if defined(_WIN32) && !defined(GLUT_DISABLE_ATEXIT_HACK)
+FGAPI void FGAPIENTRY __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int));
+FGAPI int FGAPIENTRY __glutCreateWindowWithExit(const char *title, void (__cdecl *exitfunc)(int));
+FGAPI int FGAPIENTRY __glutCreateMenuWithExit(void (* func)(int), void (__cdecl *exitfunc)(int));
+#ifndef FREEGLUT_BUILDING_LIB
+static void FGAPIENTRY glutInit_ATEXIT_HACK(int *argcp, char **argv) { __glutInitWithExit(argcp, argv, exit); }
+#define glutInit glutInit_ATEXIT_HACK
+static int FGAPIENTRY glutCreateWindow_ATEXIT_HACK(const char *title) { return __glutCreateWindowWithExit(title, exit); }
+#define glutCreateWindow glutCreateWindow_ATEXIT_HACK
+static int FGAPIENTRY glutCreateMenu_ATEXIT_HACK(void (* func)(int)) { return __glutCreateMenuWithExit(func, exit); }
+#define glutCreateMenu glutCreateMenu_ATEXIT_HACK
+#endif
+#endif
+
 #ifdef __cplusplus
     }
 #endif
index 01dabc7..9b4eb09 100644 (file)
@@ -25,6 +25,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#define FREEGLUT_BUILDING_LIB
 #include <GL/freeglut.h>
 #include "freeglut_internal.h"
 
@@ -853,6 +854,16 @@ void FGAPIENTRY glutInit( int* pargc, char** argv )
     }
 }
 
+#ifdef _WIN32
+void (__cdecl *__glutExitFunc)( int retval ) = NULL;
+
+void FGAPIENTRY __glutInitWithExit( int *argcp, char **argv, void (__cdecl *exitfunc)(int) )
+{
+  __glutExitFunc = exitfunc;
+  glutInit(argcp, argv);
+}
+#endif
+
 /*
  * Undoes all the "glutInit" stuff
  */
index e7540b0..05cdddf 100644 (file)
@@ -933,6 +933,10 @@ int fgHintPresent(Window window, Atom property, Atom hint);
 
 SFG_Proc fghGetProcAddress( const char *procName );
 
+#ifdef _WIN32
+extern void (__cdecl *__glutExitFunc)( int retval );
+#endif
+
 #endif /* FREEGLUT_INTERNAL_H */
 
 /*** END OF FILE ***/
index a96f5d6..8a04d0b 100644 (file)
@@ -25,6 +25,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#define FREEGLUT_BUILDING_LIB
 #include <GL/freeglut.h>
 #include "freeglut_internal.h"
 
@@ -778,6 +779,12 @@ int FGAPIENTRY glutCreateMenu( void(* callback)( int ) )
     return fgCreateMenu( callback )->ID;
 }
 
+int FGAPIENTRY __glutCreateMenuWithExit( void(* callback)( int ), void (__cdecl *exitfunc)(int) )
+{
+  __glutExitFunc = exitfunc;
+  return glutCreateMenu( callback );
+}
+
 /*
  * Destroys a menu object, removing all references to it
  */
index 005074b..03a3b25 100644 (file)
@@ -25,6 +25,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#define FREEGLUT_BUILDING_LIB
 #include <GL/freeglut.h>
 #include "freeglut_internal.h"
 
@@ -1092,6 +1093,14 @@ int FGAPIENTRY glutCreateWindow( const char* title )
                            GL_FALSE, GL_FALSE )->ID;
 }
 
+#ifdef _WIN32
+int FGAPIENTRY __glutCreateWindowWithExit( const char *title, void (__cdecl *exitfunc)(int) )
+{
+  __glutExitFunc = exitfunc;
+  return glutCreateWindow( title );
+}
+#endif
+
 /*
  * This function creates a sub window.
  */
index 7618307..5bf3ca0 100644 (file)
@@ -154,3 +154,6 @@ EXPORTS
        glutGetModeValues
        glutInitContextFlags
        glutInitContextVersion
+       __glutInitWithExit
+       __glutCreateWindowWithExit
+       __glutCreateMenuWithExit