[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [19775] trunk/blender/source/gameengine: Added m_zombie to the base python class (PyObjectPlus), when this is set all the subclasses will raise an error on access to their members .

Campbell Barton ideasman42 at gmail.com
Fri Apr 17 22:06:09 CEST 2009


Revision: 19775
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=19775
Author:   campbellbarton
Date:     2009-04-17 22:06:06 +0200 (Fri, 17 Apr 2009)

Log Message:
-----------
Added m_zombie to the base python class (PyObjectPlus), when this is set all the subclasses will raise an error on access to their members.

Other small changes...
- KX_Camera and KX_Light didnt have get/setitem access in their PyType definition.
- CList.from_id() error checking for a long was checking for -1 against an unsigned value (own fault)
- CValue::SpecialRelease was incrementing an int for no reason.
- renamed m_attrlist to m_attr_dict since its a PyDict type.
- removed custom getattro/setattro functions for KX_Scene and KX_GameObject, use py_base_getattro, py_base_setattro for all subclasses of PyObjectPlus.
- lowercase windows.h in VideoBase.cpp for cross compiling.

Modified Paths:
--------------
    trunk/blender/source/gameengine/Expressions/ListValue.cpp
    trunk/blender/source/gameengine/Expressions/PyObjectPlus.cpp
    trunk/blender/source/gameengine/Expressions/PyObjectPlus.h
    trunk/blender/source/gameengine/Expressions/Value.cpp
    trunk/blender/source/gameengine/Expressions/Value.h
    trunk/blender/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
    trunk/blender/source/gameengine/Ketsji/KX_Camera.cpp
    trunk/blender/source/gameengine/Ketsji/KX_GameObject.cpp
    trunk/blender/source/gameengine/Ketsji/KX_GameObject.h
    trunk/blender/source/gameengine/Ketsji/KX_Light.cpp
    trunk/blender/source/gameengine/Ketsji/KX_Scene.cpp
    trunk/blender/source/gameengine/Ketsji/KX_Scene.h
    trunk/blender/source/gameengine/VideoTexture/VideoBase.cpp

Modified: trunk/blender/source/gameengine/Expressions/ListValue.cpp
===================================================================
--- trunk/blender/source/gameengine/Expressions/ListValue.cpp	2009-04-17 13:42:40 UTC (rev 19774)
+++ trunk/blender/source/gameengine/Expressions/ListValue.cpp	2009-04-17 20:06:06 UTC (rev 19775)
@@ -513,7 +513,7 @@
 	BGE_ID_TYPE id= PyLong_FromUnsignedLongLong(value);
 #endif
 	
-	if (id==-1 && PyErr_Occurred())
+	if (PyErr_Occurred())
 		return NULL;
 
 	int numelem = GetCount();

Modified: trunk/blender/source/gameengine/Expressions/PyObjectPlus.cpp
===================================================================
--- trunk/blender/source/gameengine/Expressions/PyObjectPlus.cpp	2009-04-17 13:42:40 UTC (rev 19774)
+++ trunk/blender/source/gameengine/Expressions/PyObjectPlus.cpp	2009-04-17 20:06:06 UTC (rev 19775)
@@ -88,6 +88,7 @@
 	MT_assert(T != NULL);
 	this->ob_type = T; 
 	_Py_NewReference(this);
+	SetZombie(false);
 };
   
 /*------------------------------
@@ -99,9 +100,15 @@
 };
 
 PyAttributeDef PyObjectPlus::Attributes[] = {
+	KX_PYATTRIBUTE_RO_FUNCTION("isValid",		PyObjectPlus, pyattr_get_is_valid),
 	{NULL} //Sentinel
 };
 
+PyObject* PyObjectPlus::pyattr_get_is_valid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{	
+	Py_RETURN_TRUE;
+}
+
 /*------------------------------
  * PyObjectPlus Parents		-- Every class, even the abstract one should have parents
 ------------------------------*/
@@ -117,10 +124,19 @@
 		if (strcmp(PyString_AsString(attr), "__dict__")==0) {
 			return py_getattr_dict(NULL, Type.tp_dict); /* no Attributes yet */
 		}
-		PyErr_SetString(PyExc_AttributeError, "attribute not found");
+		PyErr_Format(PyExc_AttributeError, "attribute \"%s\" not found", PyString_AsString(attr));
 		return NULL;
 	} else {
-		return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, (PyObject *)this); \
+		/* Copied from py_getattro_up */
+		if (PyCObject_Check(descr)) {
+			return py_get_attrdef((void *)this, (const PyAttributeDef*)PyCObject_AsVoidPtr(descr));
+		} else if (descr->ob_type->tp_descr_get) {
+			return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, (PyObject *)this);
+		} else {
+			fprintf(stderr, "Unknown attribute type (PyObjectPlus::py_getattro)");
+			return descr;
+		}
+		/* end py_getattro_up copy */
 	}
   //if (streq(attr, "type"))
   //  return Py_BuildValue("s", (*(GetParents()))->tp_name);

Modified: trunk/blender/source/gameengine/Expressions/PyObjectPlus.h
===================================================================
--- trunk/blender/source/gameengine/Expressions/PyObjectPlus.h	2009-04-17 13:42:40 UTC (rev 19774)
+++ trunk/blender/source/gameengine/Expressions/PyObjectPlus.h	2009-04-17 20:06:06 UTC (rev 19775)
@@ -400,10 +400,11 @@
 	
 public:
 	PyObjectPlus(PyTypeObject *T);
+	bool m_zombie;
 	
 	virtual ~PyObjectPlus();					// destructor
 	static void PyDestructor(PyObject *P)				// python wrapper
-	{  
+	{
 		delete ((PyObjectPlus *) P);  
 	};
 	
@@ -417,6 +418,14 @@
 	virtual PyObject *py_getattro(PyObject *attr);			// py_getattro method
 	static  PyObject *py_base_getattro(PyObject * self, PyObject *attr) 	// This should be the entry in Type. 
 	{
+		if (((PyObjectPlus*)self)->IsZombie()) {
+			if (!strcmp(PyString_AsString(attr), "isValid")) {
+				Py_RETURN_FALSE;
+			}
+			((PyObjectPlus*)self)->IsZombiePyErr(); /* raise an error */
+			return NULL;
+		}
+		
 		return ((PyObjectPlus*) self)->py_getattro(attr); 
 	}
 	
@@ -432,10 +441,16 @@
 	virtual int py_setattro(PyObject *attr, PyObject *value);		// py_setattro method
 	static  int py_base_setattro(PyObject *self, PyObject *attr, PyObject *value) // the PyType should reference this
 	{
+		if (((PyObjectPlus*)self)->IsZombie()) {
+			/* you cant set isValid anyway */
+			((PyObjectPlus*)self)->IsZombiePyErr();
+			return -1;
+		}
+		
 		if (value==NULL)
-			return ((PyObjectPlus*) self)->py_delattro(attr);
+			return ((PyObjectPlus*)self)->py_delattro(attr);
 		
-		return ((PyObjectPlus*) self)->py_setattro(attr, value); 
+		return ((PyObjectPlus*)self)->py_setattro(attr, value); 
 	}
 	
 	virtual PyObject *py_repr(void);				// py_repr method
@@ -452,6 +467,41 @@
 	{
 		return ((PyObjectPlus*)self)->Py_isA(value);
 	}
+	
+	/* Kindof dumb, always returns True, the false case is checked for, before this function gets accessed */
+	static PyObject*	pyattr_get_is_valid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+	
+	bool IsZombie()
+	{
+		return m_zombie;
+	}
+	
+	bool IsZombiePyErr()
+	{
+		if(m_zombie) {
+			/*
+			PyObject *this_pystr = PyObject_Repr(this);
+			
+			PyErr_Format(
+					PyExc_RuntimeError,
+					"\"%s\" of type \"%s\" has been freed by the blender game engine, "
+					"scripts cannot access this anymore, check for this case with the \"isValid\" attribute",
+					PyString_AsString(this_pystr), ob_type->tp_name );
+			
+			Py_DECREF(this_pystr);
+			*/
+			
+			PyErr_SetString(PyExc_RuntimeError, "This value has been freed by the blender game engine but python is still holding a reference, this value cant be used.");
+		}
+		
+		return m_zombie;
+	}
+	
+	void SetZombie(bool is_zombie)
+	{
+		m_zombie= is_zombie;
+	}
+	
 };
 
 PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict);

Modified: trunk/blender/source/gameengine/Expressions/Value.cpp
===================================================================
--- trunk/blender/source/gameengine/Expressions/Value.cpp	2009-04-17 13:42:40 UTC (rev 19774)
+++ trunk/blender/source/gameengine/Expressions/Value.cpp	2009-04-17 20:06:06 UTC (rev 19775)
@@ -602,6 +602,12 @@
 	// Decrease local reference count, if it reaches 0 the object should be freed
 	if (--m_refcount > 0)
 	{
+		// Benoit suggest this as a way to automatically set the zombie flag, but I couldnt get it working - Campbell
+		/*
+		if (m_refcount == 1 && ob_refcnt > 1)
+			SetZombie(true); // the remaining refcount is held by Python!!
+		*/	
+		
 		// Reference count normal, return new reference count
 		return m_refcount;
 	}
@@ -609,6 +615,7 @@
 	{
 		// Reference count reached 0, delete ourselves and return 0
 //		MT_assert(m_refcount==0, "Reference count reached sub-zero, object released too much");
+		
 		delete this;
 		return 0;
 	}

Modified: trunk/blender/source/gameengine/Expressions/Value.h
===================================================================
--- trunk/blender/source/gameengine/Expressions/Value.h	2009-04-17 13:42:40 UTC (rev 19774)
+++ trunk/blender/source/gameengine/Expressions/Value.h	2009-04-17 20:06:06 UTC (rev 19775)
@@ -219,7 +219,7 @@
 	//static PyObject*	PyMake(PyObject*,PyObject*);
 	virtual PyObject *py_repr(void)
 	{
-		return Py_BuildValue("s",(const char*)GetText());
+		return PyString_FromString((const char*)GetText());
 	}
 
 
@@ -228,14 +228,10 @@
 
 	void	SpecialRelease()
 	{
-		int i=0;
-		if (ob_refcnt == 0)
+		if (ob_refcnt == 0) /* make sure python always holds a reference */
 		{
 			_Py_NewReference(this);
 			
-		} else
-		{
-			i++;
 		}
 		Release();
 	}
@@ -280,6 +276,7 @@
 	int					GetRefCount()											{ return m_refcount; }
 	virtual	CValue*		AddRef();												// Add a reference to this value
 	virtual int			Release();												// Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
+	
 
 	/// Property Management
 	virtual void		SetProperty(const STR_String& name,CValue* ioProperty);						// Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
@@ -355,6 +352,7 @@
 	std::map<STR_String,CValue*>*		m_pNamedPropertyArray;									// Properties for user/game etc
 	ValueFlags			m_ValFlags;												// Frequently used flags in a bitfield (low memoryusage)
 	int					m_refcount;												// Reference Counter	
+	bool				m_zombie;												// Object is invalid put its still being referenced (by python)
 	static	double m_sZeroVec[3];	
 	static bool			m_ignore_deprecation_warnings;
 

Modified: trunk/blender/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
===================================================================
--- trunk/blender/source/gameengine/GameLogic/SCA_PropertyActuator.cpp	2009-04-17 13:42:40 UTC (rev 19774)
+++ trunk/blender/source/gameengine/GameLogic/SCA_PropertyActuator.cpp	2009-04-17 20:06:06 UTC (rev 19775)
@@ -95,7 +95,7 @@
 		}
 		newval->Release();
 	}
-	else if (userexpr = parser.ProcessText(m_exprtxt)) {
+	else if ((userexpr = parser.ProcessText(m_exprtxt))) {
 		switch (m_type)
 		{
 

Modified: trunk/blender/source/gameengine/Ketsji/KX_Camera.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_Camera.cpp	2009-04-17 13:42:40 UTC (rev 19774)
+++ trunk/blender/source/gameengine/Ketsji/KX_Camera.cpp	2009-04-17 20:06:06 UTC (rev 19775)
@@ -517,13 +517,20 @@
 		0,
 		0,
 		py_base_repr,
-		0,0,0,0,0,0,
+		0,0,
+		&KX_GameObject::Mapping,
+		0,0,0,
 		py_base_getattro,
 		py_base_setattro,
 		0,0,0,0,0,0,0,0,0,
 		Methods
 };
 
+
+
+
+
+
 PyParentObject KX_Camera::Parents[] = {
 	&KX_Camera::Type,
 	&KX_GameObject::Type,
@@ -534,22 +541,11 @@
 
 PyObject* KX_Camera::py_getattro(PyObject *attr)
 {
-	if (ValidPythonToGameObject(this)==false) {
-		if (!strcmp(PyString_AsString(attr), "isValid")) {
-			PyErr_Clear();
-			Py_RETURN_FALSE;
-		}
-		return NULL; /* ValidPythonToGameObject sets the error */
-	}
-	
 	py_getattro_up(KX_GameObject);
 }
 
 int KX_Camera::py_setattro(PyObject *attr, PyObject *value)
-{
-	if (ValidPythonToGameObject(this)==false)
-		return -1;
-	
+{	
 	py_setattro_up(KX_GameObject);
 }
 

Modified: trunk/blender/source/gameengine/Ketsji/KX_GameObject.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_GameObject.cpp	2009-04-17 13:42:40 UTC (rev 19774)
+++ trunk/blender/source/gameengine/Ketsji/KX_GameObject.cpp	2009-04-17 20:06:06 UTC (rev 19775)
@@ -103,7 +103,7 @@
 	m_xray(false),
 	m_pHitObject(NULL),
 	m_isDeformable(false),
-	m_attrlist(NULL)
+	m_attr_dict(NULL)
 {
 	m_ignore_activity_culling = false;
 	m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
@@ -146,9 +146,9 @@
 		delete m_pGraphicController;
 	}
 	
-	if (m_attrlist) {
-		PyDict_Clear(m_attrlist); /* incase of circular refs or other weired cases */
-		Py_DECREF(m_attrlist);
+	if (m_attr_dict) {
+		PyDict_Clear(m_attr_dict); /* incase of circular refs or other weired cases */
+		Py_DECREF(m_attr_dict);
 	}
 }
 
@@ -339,8 +339,8 @@

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list