[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [20434] trunk/blender/source: BGE PyAPI Bug reported by Pitel on blenderartist.

Campbell Barton ideasman42 at gmail.com
Tue May 26 20:06:10 CEST 2009


Revision: 20434
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20434
Author:   campbellbarton
Date:     2009-05-26 20:06:09 +0200 (Tue, 26 May 2009)

Log Message:
-----------
BGE PyAPI Bug reported by Pitel on blenderartist.
importing "pygame" failed when running the BGE for the second time.

Rather then clearing modules, backup and restore them (as its doing with sys.path)

This way the BGE will never remember any modules imported during game play (which can cause bugs/crashes), but it also wont break pythons state by possibly removing modules that are being used internally.

Modified Paths:
--------------
    trunk/blender/source/blender/python/api2_2x/bpy_internal_import.c
    trunk/blender/source/blender/python/api2_2x/bpy_internal_import.h
    trunk/blender/source/gameengine/Ketsji/KX_PythonInit.cpp

Modified: trunk/blender/source/blender/python/api2_2x/bpy_internal_import.c
===================================================================
--- trunk/blender/source/blender/python/api2_2x/bpy_internal_import.c	2009-05-26 17:20:22 UTC (rev 20433)
+++ trunk/blender/source/blender/python/api2_2x/bpy_internal_import.c	2009-05-26 18:06:09 UTC (rev 20434)
@@ -281,6 +281,7 @@
  * even if we remove a python module a reimport will bring it back again.
  */
 
+#if 0 // not used anymore but may still come in handy later
 
 #if defined(WIN32) || defined(WIN64)
 #define SEPSTR "\\"
@@ -336,4 +337,4 @@
 	
 	Py_DECREF(list); /* removes all references from append */
 }
-
+#endif

Modified: trunk/blender/source/blender/python/api2_2x/bpy_internal_import.h
===================================================================
--- trunk/blender/source/blender/python/api2_2x/bpy_internal_import.h	2009-05-26 17:20:22 UTC (rev 20433)
+++ trunk/blender/source/blender/python/api2_2x/bpy_internal_import.h	2009-05-26 18:06:09 UTC (rev 20434)
@@ -37,7 +37,7 @@
 
 PyObject*	bpy_text_import( char *name, int *found );
 PyObject*	bpy_text_reimport( PyObject *module, int *found );
-void		bpy_text_clear_modules( int clear_all ); /* Clear user modules */
+/* void		bpy_text_clear_modules( int clear_all );*/ /* Clear user modules */ 
 extern PyMethodDef bpy_import_meth[];
 extern PyMethodDef bpy_reload_meth[];
 

Modified: trunk/blender/source/gameengine/Ketsji/KX_PythonInit.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_PythonInit.cpp	2009-05-26 17:20:22 UTC (rev 20433)
+++ trunk/blender/source/gameengine/Ketsji/KX_PythonInit.cpp	2009-05-26 18:06:09 UTC (rev 20434)
@@ -112,7 +112,6 @@
 #include "GPU_material.h"
 
 static void setSandbox(TPythonSecurityLevel level);
-static void clearGameModules();
 
 // 'local' copy of canvas ptr, for window height/width python scripts
 static RAS_ICanvas* gp_Canvas = NULL;
@@ -122,6 +121,7 @@
 static char gp_GamePythonPath[FILE_MAXDIR + FILE_MAXFILE] = "";
 static char gp_GamePythonPathOrig[FILE_MAXDIR + FILE_MAXFILE] = ""; // not super happy about this, but we need to remember the first loaded file for the global/dict load save
 static PyObject *gp_OrigPythonSysPath= NULL;
+static PyObject *gp_OrigPythonSysModules= NULL;
 
 void	KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color)
 {
@@ -1465,9 +1465,9 @@
 
 /* Explanation of 
  * 
- * - backupPySysPath()		: stores sys.path in gp_OrigPythonSysPath
- * - initPySysPath(main)	: initializes the blendfile and library paths
- * - restorePySysPath()		: restores sys.path from gp_OrigPythonSysPath
+ * - backupPySysObjects()		: stores sys.path in gp_OrigPythonSysPath
+ * - initPySysObjects(main)	: initializes the blendfile and library paths
+ * - restorePySysObjects()		: restores sys.path from gp_OrigPythonSysPath
  * 
  * These exist so the current blend dir "//" can always be used to import modules from.
  * the reason we need a few functions for this is that python is not only used by the game engine
@@ -1482,23 +1482,27 @@
 /**
  * So we can have external modules mixed with our blend files.
  */
-static void backupPySysPath(void)
+static void backupPySysObjects(void)
 {
 	PyObject *sys_path= PySys_GetObject("path"); /* should never fail */
+	PyObject *sys_mods= PySys_GetObject("modules"); /* should never fail */
 	
-	/* just incase its set */
-	Py_XDECREF(gp_OrigPythonSysPath);
-	gp_OrigPythonSysPath= NULL;
-	
+	/* paths */
+	Py_XDECREF(gp_OrigPythonSysPath); /* just incase its set */
 	gp_OrigPythonSysPath = PyList_GetSlice(sys_path, 0, INT_MAX); /* copy the list */
+	
+	/* modules */
+	Py_XDECREF(gp_OrigPythonSysModules); /* just incase its set */
+	gp_OrigPythonSysModules = PyDict_Copy(sys_mods); /* copy the list */
+	
 }
 
-/* for initPySysPath only,
+/* for initPySysObjects only,
  * takes a blend path and adds a scripts dir from it
  *
  * "/home/me/foo.blend" -> "/home/me/scripts"
  */
-static void initPySysPath__append(PyObject *sys_path, char *filename)
+static void initPySysObjects__append(PyObject *sys_path, char *filename)
 {
 	PyObject *item;
 	char expanded[FILE_MAXDIR + FILE_MAXFILE];
@@ -1515,13 +1519,13 @@
 	
 	Py_DECREF(item);
 }
-static void initPySysPath(Main *maggie)
+static void initPySysObjects(Main *maggie)
 {
 	PyObject *sys_path= PySys_GetObject("path"); /* should never fail */
 	
 	if (gp_OrigPythonSysPath==NULL) {
 		/* backup */
-		backupPySysPath();
+		backupPySysObjects();
 	}
 	else {
 		/* get the original sys path when the BGE started */
@@ -1531,27 +1535,36 @@
 	Library *lib= (Library *)maggie->library.first;
 	
 	while(lib) {
-		initPySysPath__append(sys_path, lib->name);
+		initPySysObjects__append(sys_path, lib->name);
 		lib= (Library *)lib->id.next;
 	}
 	
-	initPySysPath__append(sys_path, gp_GamePythonPath);
+	initPySysObjects__append(sys_path, gp_GamePythonPath);
 	
 //	fprintf(stderr, "\nNew Path: %d ", PyList_Size(sys_path));
 //	PyObject_Print(sys_path, stderr, 0);
 }
 
-static void restorePySysPath(void)
+static void restorePySysObjects(void)
 {
 	if (gp_OrigPythonSysPath==NULL)
 		return;
 	
 	PyObject *sys_path= PySys_GetObject("path"); /* should never fail */
-	
+	PyObject *sys_mods= PySys_GetObject("modules"); /* should never fail */
+
+	/* paths */
 	PyList_SetSlice(sys_path, 0, INT_MAX, gp_OrigPythonSysPath);
 	Py_DECREF(gp_OrigPythonSysPath);
 	gp_OrigPythonSysPath= NULL;
 	
+	/* modules */
+	PyDict_Clear(sys_mods);
+	PyDict_Update(sys_mods, gp_OrigPythonSysModules);
+	Py_DECREF(gp_OrigPythonSysModules);
+	gp_OrigPythonSysModules= NULL;	
+	
+	
 //	fprintf(stderr, "\nRestore Path: %d ", PyList_Size(sys_path));
 //	PyObject_Print(sys_path, stderr, 0);
 }
@@ -1588,7 +1601,7 @@
 	
 	bpy_import_main_set(maggie);
 	
-	initPySysPath(maggie);
+	initPySysObjects(maggie);
 	
 	first_time = false;
 	
@@ -1599,11 +1612,9 @@
 }
 
 void exitGamePlayerPythonScripting()
-{
-	//clearGameModules(); // were closing python anyway
-	
+{	
 	/* since python restarts we cant let the python backup of the sys.path hang around in a global pointer */
-	restorePySysPath(); /* get back the original sys.path and clear the backup */
+	restorePySysObjects(); /* get back the original sys.path and clear the backup */
 	
 	Py_Finalize();
 	bpy_import_main_set(NULL);
@@ -1629,10 +1640,7 @@
 	
 	bpy_import_main_set(maggie);
 	
-	initPySysPath(maggie);
-	
-	/* clear user defined modules that may contain data from the last run */
-	clearGameModules();
+	initPySysObjects(maggie);
 
 	PyObjectPlus::NullDeprecationWarning();
 	
@@ -1640,46 +1648,9 @@
 	return PyModule_GetDict(moduleobj);
 }
 
-static void clearModule(PyObject *modules, const char *name)
-{
-	PyObject *mod= PyDict_GetItemString(modules, name);
-	
-	if (mod==NULL)
-		return;
-	
-	PyDict_Clear(PyModule_GetDict(mod)); /* incase there are any circular refs */
-	PyDict_DelItemString(modules, name);
-}
-
-static void clearGameModules()
-{
-	/* references to invalid BGE data is better supported in 2.49+ so dont clear dicts */
-#if 0
-	/* Note, user modules could still reference these modules
-	 * but since the dict's are cleared their members wont be accessible */
-	
-	PyObject *modules= PySys_GetObject((char *)"modules");
-	clearModule(modules, "Expression");
-	clearModule(modules, "CValue");	
-	clearModule(modules, "PhysicsConstraints");	
-	clearModule(modules, "GameLogic");	
-	clearModule(modules, "Rasterizer");	
-	clearModule(modules, "GameKeys");	
-	clearModule(modules, "VideoTexture");
-	clearModule(modules, "Mathutils");	
-	clearModule(modules, "Geometry");	
-	clearModule(modules, "BGL");	
-	PyErr_Clear(); // incase some of these were alredy removed.
-#endif
-	
-	/* clear user defined modules, arg '1' for clear external py modules too */
-	bpy_text_clear_modules(1);
-}
-
 void exitGamePythonScripting()
 {
-	clearGameModules();
-	restorePySysPath(); /* get back the original sys.path and clear the backup */
+	restorePySysObjects(); /* get back the original sys.path and clear the backup */
 	bpy_import_main_set(NULL);
 	PyObjectPlus::ClearDeprecationWarning();
 }





More information about the Bf-blender-cvs mailing list