mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-07 04:20:07 +01:00
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:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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...
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user