A little black magic... When the C++ object (for a window or

whatever) is deleted there is no way to force the Python shadow object
to also be destroyed and clean up all references to it.  This leads to
crashes if the shadow object tries to call a method with the old C++
pointer...  The black magic I've done is to replace the __class__ in the
Python instanc object with a class that raises an exception whenever a
method call is attempted.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15059 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2002-04-09 22:01:45 +00:00
parent 31fa82942c
commit 4acff284f9
18 changed files with 207 additions and 84 deletions

View File

@@ -101,6 +101,9 @@ bool wxRealPoint_helper(PyObject* source, wxRealPoint** obj);
bool wxRect_helper(PyObject* source, wxRect** obj);
bool wxColour_helper(PyObject* source, wxColour** obj);
//----------------------------------------------------------------------
// Other helpful stuff
#if PYTHON_API_VERSION < 1009
#define PySequence_Fast_GET_ITEM(o, i) \
(PyList_Check(o) ? PyList_GET_ITEM(o, i) : PyTuple_GET_ITEM(o, i))
@@ -113,9 +116,9 @@ bool _4int_seq_helper(PyObject* source, int* i1, int* i2, int* i3, int* i4);
PyObject* wxArrayString2PyList_helper(const wxArrayString& arr);
PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr);
#define RETURN_NONE() { Py_INCREF(Py_None); return Py_None; }
#define DECLARE_DEF_STRING(name) static wxString wxPy##name(wx##name)
#define RETURN_NONE() { Py_INCREF(Py_None); return Py_None; }
#define DECLARE_DEF_STRING(name) static const wxString wxPy##name(wx##name)
#define DECLARE_DEF_STRING2(name,val) static const wxString wxPy##name(val)
//----------------------------------------------------------------------
@@ -201,6 +204,18 @@ public:
};
//----------------------------------------------------------------------
// Forward decalre a few things used in the exported API
class wxPyClientData;
class wxPyUserData;
class wxPyOORClientData;
void wxPyClientData_dtor(wxPyClientData* self);
void wxPyUserData_dtor(wxPyUserData* self);
void wxPyOORClientData_dtor(wxPyOORClientData* self);
//---------------------------------------------------------------------------
// Export a C API in a struct. Other modules will be able to load this from
// the wxc module and will then have safe access to these functions, even if
@@ -256,12 +271,70 @@ struct wxPyCoreAPI {
void (*p_wxPyPtrTypeMap_Add)(const char* commonName, const char* ptrName);
PyObject* (*p_wxArrayString2PyList_helper)(const wxArrayString& arr);
PyObject* (*p_wxArrayInt2PyList_helper)(const wxArrayInt& arr);
void (*p_wxPyClientData_dtor)(wxPyClientData*);
void (*p_wxPyUserData_dtor)(wxPyUserData*);
void (*p_wxPyOORClientData_dtor)(wxPyOORClientData*);
};
#ifdef wxPyUSE_EXPORT
static wxPyCoreAPI* wxPyCoreAPIPtr = NULL; // Each module needs one, but may not use it.
static wxPyCoreAPI* wxPyCoreAPIPtr = NULL; // Each module needs one, but doesn't have to use it.
#endif
//---------------------------------------------------------------------------
class wxPyUserData : public wxObject {
public:
wxPyUserData(PyObject* obj) {
m_obj = obj;
Py_INCREF(m_obj);
}
~wxPyUserData() {
#ifdef wxPyUSE_EXPORT
wxPyCoreAPIPtr->p_wxPyUserData_dtor(this);
#else
wxPyUserData_dtor(this);
#endif
}
PyObject* m_obj;
};
class wxPyClientData : public wxClientData {
public:
wxPyClientData(PyObject* obj) {
m_obj = obj;
Py_INCREF(m_obj);
}
~wxPyClientData() {
#ifdef wxPyUSE_EXPORT
wxPyCoreAPIPtr->p_wxPyClientData_dtor(this);
#else
wxPyClientData_dtor(this);
#endif
}
PyObject* m_obj;
};
class wxPyOORClientData : public wxPyClientData {
public:
wxPyOORClientData(PyObject* obj)
: wxPyClientData(obj) {}
~wxPyOORClientData() {
#ifdef wxPyUSE_EXPORT
wxPyCoreAPIPtr->p_wxPyOORClientData_dtor(this);
#else
wxPyOORClientData_dtor(this);
#endif
}
};
//---------------------------------------------------------------------------
// This class holds an instance of a Python Shadow Class object and assists
// with looking up and invoking Python callback methods from C++ virtual
@@ -312,53 +385,6 @@ void wxPyCBH_delete(wxPyCallbackHelper* cbh);
//----------------------------------------------------------------------
class wxPyUserData : public wxObject {
public:
wxPyUserData(PyObject* obj) {
m_obj = obj;
Py_INCREF(m_obj);
}
~wxPyUserData() {
#ifdef wxPyUSE_EXPORT
wxPyCoreAPIPtr->p_wxPyBeginBlockThreads();
Py_DECREF(m_obj);
wxPyCoreAPIPtr->p_wxPyEndBlockThreads();
#else
wxPyBeginBlockThreads();
Py_DECREF(m_obj);
wxPyEndBlockThreads();
#endif
}
PyObject* m_obj;
};
class wxPyClientData : public wxClientData {
public:
wxPyClientData(PyObject* obj) {
m_obj = obj;
Py_INCREF(m_obj);
}
~wxPyClientData() {
#ifdef wxPyUSE_EXPORT
wxPyCoreAPIPtr->p_wxPyBeginBlockThreads();
Py_DECREF(m_obj);
wxPyCoreAPIPtr->p_wxPyEndBlockThreads();
#else
wxPyBeginBlockThreads();
Py_DECREF(m_obj);
wxPyEndBlockThreads();
#endif
}
PyObject* m_obj;
};
//---------------------------------------------------------------------------
// These macros are used to implement the virtual methods that should