diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-02-25 17:32:35 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-02-25 17:32:35 +0300 |
commit | 2cf20fde1b2f3494b8bd12e73fb9ccc17959f536 (patch) | |
tree | 875feaaf82672de1dd74034327f4641a26ac6485 | |
parent | 60b22c5d1281a01f0675988d37fe002c7c2a6a98 (diff) |
patch [#26215] Python weak reference (weakref) support for game objects
by Alex Fraser (z0r)
-rw-r--r-- | source/gameengine/Expressions/PyObjectPlus.cpp | 37 | ||||
-rw-r--r-- | source/gameengine/Expressions/PyObjectPlus.h | 7 |
2 files changed, 34 insertions, 10 deletions
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index a3c1e24cdf6..84d6a1cba4b 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -108,19 +108,26 @@ void PyObjectPlus::InvalidateProxy() // check typename of each parent PyTypeObject PyObjectPlus::Type = { PyVarObject_HEAD_INIT(NULL, 0) - "PyObjectPlus", /*tp_name*/ + "PyObjectPlus", /*tp_name*/ sizeof(PyObjectPlus_Proxy), /*tp_basicsize*/ - 0, /*tp_itemsize*/ + 0, /*tp_itemsize*/ /* methods */ - py_base_dealloc, - 0, - 0, - 0, + py_base_dealloc, /* tp_dealloc */ + 0, /* printfunc tp_print; */ + 0, /* getattrfunc tp_getattr; */ + 0, /* setattrfunc tp_setattr; */ + 0, /* tp_compare */ /* DEPRECATED in python 3.0! */ + py_base_repr, /* tp_repr */ + 0,0,0,0,0,0,0,0,0, /* Method suites for standard classes */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,/* long tp_flags; */ + 0,0,0,0, + /* weak reference enabler */ +#ifdef USE_WEAKREFS + offsetof(PyObjectPlus_Proxy, in_weakreflist), /* long tp_weaklistoffset; */ +#else 0, - py_base_repr, - 0,0,0,0,0,0,0,0,0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - 0,0,0,0,0,0,0, +#endif + 0,0, Methods, 0, 0, @@ -209,8 +216,16 @@ PyObject * PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObjec return (PyObject *)ret; } +/** + * @param self A PyObjectPlus_Proxy + */ void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper { +#ifdef USE_WEAKREFS + if (BGE_PROXY_WKREF(self) != NULL) + PyObject_ClearWeakRefs((PyObject *) self); +#endif + if (BGE_PROXY_PYREF(self)) { PyObjectPlus *self_plus= BGE_PROXY_REF(self); if(self_plus) { @@ -1107,6 +1122,7 @@ PyObject *PyObjectPlus::GetProxyPlus_Ext(PyObjectPlus *self, PyTypeObject *tp, v self->m_proxy = reinterpret_cast<PyObject *>PyObject_NEW( PyObjectPlus_Proxy, tp); BGE_PROXY_PYOWNS(self->m_proxy) = false; BGE_PROXY_PYREF(self->m_proxy) = true; + BGE_PROXY_WKREF(self->m_proxy) = NULL; } //PyObject_Print(self->m_proxy, stdout, 0); //printf("ref %d\n", self->m_proxy->ob_refcnt); @@ -1127,6 +1143,7 @@ PyObject *PyObjectPlus::NewProxyPlus_Ext(PyObjectPlus *self, PyTypeObject *tp, v BGE_PROXY_PYOWNS(proxy) = py_owns; BGE_PROXY_REF(proxy) = NULL; BGE_PROXY_PTR(proxy) = ptr; + BGE_PROXY_WKREF(self->m_proxy) = NULL; return proxy; } if (self->m_proxy) diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 12ae31f6c82..315a328317d 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -31,6 +31,9 @@ * \ingroup expressions */ +/* for now keep weakrefs optional */ +#define USE_WEAKREFS + #ifndef _adr_py_lib_h_ // only process once, #define _adr_py_lib_h_ // even if multiply included @@ -95,6 +98,9 @@ typedef struct PyObjectPlus_Proxy { void *ptr; // optional pointer to generic structure, the structure holds no reference to this proxy bool py_owns; // true if the object pointed by ref should be deleted when the proxy is deleted bool py_ref; // true if proxy is connected to a GE object (ref is used) +#ifdef USE_WEAKREFS + PyObject *in_weakreflist; // weak reference enabler +#endif } PyObjectPlus_Proxy; #define BGE_PROXY_ERROR_MSG "Blender Game Engine data has been freed, cannot use this python variable" @@ -102,6 +108,7 @@ typedef struct PyObjectPlus_Proxy { #define BGE_PROXY_PTR(_self) (((PyObjectPlus_Proxy *)_self)->ptr) #define BGE_PROXY_PYOWNS(_self) (((PyObjectPlus_Proxy *)_self)->py_owns) #define BGE_PROXY_PYREF(_self) (((PyObjectPlus_Proxy *)_self)->py_ref) +#define BGE_PROXY_WKREF(_self) (((PyObjectPlus_Proxy *)_self)->in_weakreflist) /* Note, sometimes we dont care what BGE type this is as long as its a proxy */ #define BGE_PROXY_CHECK_TYPE(_type) ((_type)->tp_dealloc == PyObjectPlus::py_base_dealloc) |