Refactor the various PyObject user-data classes to share a common templated base class

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@71614 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2012-05-30 23:33:53 +00:00
parent b2224f6492
commit bbbe85b554
4 changed files with 94 additions and 91 deletions

View File

@@ -11,29 +11,15 @@
%ModuleHeaderCode
// A wxClientData that holds a reference to a Python object
class wxPyClientData : public wxClientData
{
public:
wxPyClientData(PyObject* obj, bool incref=true)
{
m_obj = obj;
m_incRef = incref;
if (incref) {
wxPyBLOCK_THREADS( Py_INCREF(m_obj) );
}
}
~wxPyClientData()
{
if (m_incRef) {
wxPyBLOCK_THREADS( Py_DECREF(m_obj) );
}
m_obj = NULL;
}
PyObject* m_obj;
bool m_incRef;
};
// A wxClientData that holds a reference to a Python object
class wxPyClientData : public wxPyUserDataHelper<wxClientData>
{
public:
wxPyClientData(PyObject* obj = NULL)
: wxPyUserDataHelper<wxClientData>(obj)
{ }
};
%End
@@ -59,13 +45,7 @@
%ConvertFromTypeCode
// Code to convert a wxClientData back to the PyObject.
PyObject* obj;
if (sipCpp == NULL) {
obj = Py_None;
} else {
wxPyClientData* data = static_cast<wxPyClientData*>(sipCpp); // TODO: verify poitner type?
obj = data->m_obj;
}
Py_INCREF(obj);
obj = wxPyClientData::SafeGetData(static_cast<wxPyClientData*>(sipCpp));
return obj;
%End

View File

@@ -15,21 +15,14 @@
#include <wx/treebase.h>
// A wxTreeItemData that knows what to do with PyObjects for maintianing the refcount
class wxPyTreeItemData : public wxTreeItemData {
class wxPyTreeItemData : public wxPyUserDataHelper<wxTreeItemData>
{
public:
wxPyTreeItemData(PyObject* obj = NULL) {
if (obj == NULL)
obj = Py_None;
wxPyBLOCK_THREADS( Py_INCREF(obj) );
m_obj = obj;
}
wxPyTreeItemData(PyObject* obj = NULL)
: wxPyUserDataHelper<wxTreeItemData>(obj)
{ }
};
~wxPyTreeItemData() {
wxPyBLOCK_THREADS( Py_DECREF(m_obj) );
}
PyObject* m_obj;
};
%End
@@ -41,7 +34,7 @@ public:
return TRUE; // any python object is valid
}
// Code to create a new wxClientData from the PyObject
// Code to create a new wxTreeItemData from the PyObject
wxPyTreeItemData* data = new wxPyTreeItemData(sipPy);
*sipCppPtr = data;
return sipGetState(sipTransferObj);
@@ -51,13 +44,7 @@ public:
%ConvertFromTypeCode
// Code to convert a wxPyTreeItemData back to the PyObject.
PyObject* obj;
if (sipCpp == NULL) {
obj = Py_None;
} else {
wxPyTreeItemData* data = static_cast<wxPyTreeItemData*>(sipCpp);
obj = data->m_obj;
}
Py_INCREF(obj);
obj = wxPyTreeItemData::SafeGetData(static_cast<wxPyTreeItemData*>(sipCpp));
return obj;
%End

View File

@@ -11,36 +11,15 @@
%ModuleHeaderCode
// A wxPyUserData object that holds a reference to a Python object
class wxPyUserData : public wxObject
{
public:
wxPyUserData() : wxObject()
{
m_obj = NULL;
m_incRef = false;
}
wxPyUserData(PyObject* obj, bool incref=true)
: wxObject()
{
m_obj = obj;
m_incRef = incref;
if (incref) {
wxPyBLOCK_THREADS( Py_INCREF(m_obj) );
}
}
virtual ~wxPyUserData()
{
if (m_incRef) {
wxPyBLOCK_THREADS( Py_DECREF(m_obj) );
}
m_obj = NULL;
}
PyObject* m_obj;
bool m_incRef;
};
// A wxObject object that holds a reference to a Python object
class wxPyUserData : public wxPyUserDataHelper<wxObject>
{
public:
wxPyUserData(PyObject* obj = NULL)
: wxPyUserDataHelper<wxObject>(obj)
{ }
};
%End
@@ -66,17 +45,8 @@
%ConvertFromTypeCode
// Code to convert a wxPyUserData back to the PyObject.
PyObject* obj;
if (sipCpp == NULL) {
obj = Py_None;
} else {
wxPyUserData* data = static_cast<wxPyUserData*>(sipCpp); // TODO: verify pointer type?
obj = data->m_obj;
}
Py_INCREF(obj);
obj = wxPyUserData::SafeGetData(static_cast<wxPyUserData*>(sipCpp));
return obj;
%End
};
// NOTE TO SELF: It looks like the GIL is already held by the current thread
// in ConvertToTypeCode and ConvertFromTypeCode code blocks...

View File

@@ -213,5 +213,71 @@ private:
wxPyBlock_t m_oldstate;
bool m_block;
};
//--------------------------------------------------------------------------
// helper template to make common code for all of the various user data owners
template<typename Base>
class wxPyUserDataHelper : public Base {
public:
explicit wxPyUserDataHelper(PyObject* obj = NULL)
: m_obj(obj ? obj : Py_None)
{
wxPyThreadBlocker blocker;
Py_INCREF(m_obj);
}
~wxPyUserDataHelper()
{ // normally the derived class does the clean up, or deliberately leaks
// by setting m_obj to 0, but if not then do it here.
if (m_obj) {
wxPyThreadBlocker blocker;
Py_DECREF(m_obj);
m_obj = 0;
}
}
// Return Value: New reference
PyObject* GetData() const {
wxPyThreadBlocker blocker;
Py_INCREF(m_obj);
return m_obj;
}
// Return Value: Borrowed reference
PyObject* BorrowData() const {
return m_obj;
}
void SetData(PyObject* obj) {
if (obj != m_obj) {
wxPyThreadBlocker blocker;
Py_DECREF(m_obj);
m_obj = obj ? obj : Py_None;
Py_INCREF(m_obj);
}
}
// Return the object in udata or None if udata is null
// Return Value: New reference
static PyObject* SafeGetData(wxPyUserDataHelper<Base>* udata) {
wxPyThreadBlocker blocker;
PyObject* obj = udata ? udata->BorrowData() : Py_None;
Py_INCREF(obj);
return obj;
}
// Set the m_obj to null, this should only be used during clean up, when
// the object should be leaked.
// Calling any other methods on this object is then undefined behaviour
void ReleaseDataDuringCleanup()
{
m_obj = 0;
}
private:
PyObject* m_obj;
};
//--------------------------------------------------------------------------
#endif