[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