X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/db0ff83efbd6105c04d5ab84c85094e887e97b9a..9fd9e47a93dfcdd99c2722e288a0f28a51ce6f5f:/wxPython/src/helpers.cpp diff --git a/wxPython/src/helpers.cpp b/wxPython/src/helpers.cpp index aa48fa7128..a1be4c1611 100644 --- a/wxPython/src/helpers.cpp +++ b/wxPython/src/helpers.cpp @@ -47,6 +47,7 @@ int WXDLLEXPORT wxEntryInitGui(); void WXDLLEXPORT wxEntryCleanup(); wxPyApp* wxPythonApp = NULL; // Global instance of application object +bool wxPyDoCleanup = FALSE; #ifdef WXP_WITH_THREAD @@ -184,6 +185,7 @@ void __wxPreStart() if (wxTopLevelWindows.Number() > 0) return; + wxPyDoCleanup = TRUE; int argc = 0; char** argv = NULL; @@ -280,7 +282,8 @@ PyObject* __wxStart(PyObject* /* self */, PyObject* args) void __wxCleanup() { - wxEntryCleanup(); + if (wxPyDoCleanup) + wxEntryCleanup(); #ifdef WXP_WITH_THREAD delete wxPyTMutex; wxPyTMutex = NULL; @@ -295,6 +298,7 @@ void __wxCleanup() { static PyObject* wxPython_dict = NULL; static PyObject* wxPyPtrTypeMap = NULL; + PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args) { @@ -334,6 +338,52 @@ PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args) return Py_None; } +//--------------------------------------------------------------------------- + +void wxPyClientData_dtor(wxPyClientData* self) { + wxPyBeginBlockThreads(); + Py_DECREF(self->m_obj); + wxPyEndBlockThreads(); +} + +void wxPyUserData_dtor(wxPyUserData* self) { + wxPyBeginBlockThreads(); + Py_DECREF(self->m_obj); + wxPyEndBlockThreads(); +} + + +// This is called when an OOR controled object is being destroyed. Although +// the C++ object is going away there is no way to force the Python object +// (and all references to it) to die too. This causes problems (crashes) in +// wxPython when a python shadow object attempts to call a C++ method using +// the now bogus pointer... So to try and prevent this we'll do a little black +// magic and change the class of the python instance to a class that will +// raise an exception for any attempt to call methods with it. See +// _wxPyDeadObject in _extras.py for the implementation of this class. +void wxPyOORClientData_dtor(wxPyOORClientData* self) { + + static PyObject* deadObjectClass = NULL; + + wxPyBeginBlockThreads(); + if (deadObjectClass == NULL) { + deadObjectClass = PyDict_GetItemString(wxPython_dict, "_wxPyDeadObject"); + wxASSERT_MSG(deadObjectClass != NULL, wxT("Can't get _wxPyDeadObject class!")); + Py_INCREF(deadObjectClass); + } + + // Clear the instance's dictionary, put the name of the old class into the + // instance, and then reset the class to be the dead class. + if (self->m_obj->ob_refcnt > 1) { // but only if there is more than one reference + wxASSERT_MSG(PyInstance_Check(self->m_obj), wxT("m_obj not an instance!?!?!")); + PyInstanceObject* inst = (PyInstanceObject*)self->m_obj; + PyDict_Clear(inst->in_dict); + PyDict_SetItemString(inst->in_dict, "_name", inst->in_class->cl_name); + inst->in_class = (PyClassObject*)deadObjectClass; + Py_INCREF(deadObjectClass); + } + wxPyEndBlockThreads(); +} //--------------------------------------------------------------------------- // Stuff used by OOR to find the right wxPython class type to return and to @@ -344,6 +394,7 @@ PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args) // is not the same as the shadow class name, for example wxPyTreeCtrl // vs. wxTreeCtrl. It needs to be referenced in Python as well as from C++, // so we'll just make it a Python dictionary in the wx module's namespace. +// (See __wxSetDictionary) void wxPyPtrTypeMap_Add(const char* commonName, const char* ptrName) { if (! wxPyPtrTypeMap) wxPyPtrTypeMap = PyDict_New(); @@ -379,7 +430,7 @@ PyObject* wxPyMake_wxObject(wxObject* source, bool checkEvtHandler) { if (checkEvtHandler && wxIsKindOf(source, wxEvtHandler)) { isEvtHandler = TRUE; wxEvtHandler* eh = (wxEvtHandler*)source; - wxPyClientData* data = (wxPyClientData*)eh->GetClientObject(); + wxPyOORClientData* data = (wxPyOORClientData*)eh->GetClientObject(); if (data) { target = data->m_obj; Py_INCREF(target); @@ -400,9 +451,9 @@ PyObject* wxPyMake_wxObject(wxObject* source, bool checkEvtHandler) { if (info) { target = wxPyConstructObject(source, name, klass, FALSE); if (target && isEvtHandler) - ((wxEvtHandler*)source)->SetClientObject(new wxPyClientData(target)); + ((wxEvtHandler*)source)->SetClientObject(new wxPyOORClientData(target)); } else { - wxString msg("wxPython class not found for "); + wxString msg(wxT("wxPython class not found for ")); msg += source->GetClassInfo()->GetClassName(); PyErr_SetString(PyExc_NameError, msg.mbc_str()); target = NULL; @@ -423,7 +474,7 @@ PyObject* wxPyMake_wxSizer(wxSizer* source) { // already be a pointer to a Python object that we can use // in the OOR data. wxSizer* sz = (wxSizer*)source; - wxPyClientData* data = (wxPyClientData*)sz->GetClientObject(); + wxPyOORClientData* data = (wxPyOORClientData*)sz->GetClientObject(); if (data) { target = data->m_obj; Py_INCREF(target); @@ -432,7 +483,7 @@ PyObject* wxPyMake_wxSizer(wxSizer* source) { if (! target) { target = wxPyMake_wxObject(source, FALSE); if (target != Py_None) - ((wxSizer*)source)->SetClientObject(new wxPyClientData(target)); + ((wxSizer*)source)->SetClientObject(new wxPyOORClientData(target)); } return target; } @@ -490,12 +541,10 @@ PyObject* wxPyConstructObject(void* ptr, PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff); if (! classobj) { - char temp[128]; - sprintf(temp, - "*** Unknown class name %s, tell Robin about it please ***", - buff); - obj = PyString_FromString(temp); - return obj; + wxString msg(wxT("wxPython class not found for ")); + msg += className; + PyErr_SetString(PyExc_NameError, msg.mbc_str()); + return NULL; } return wxPyConstructObject(ptr, className, classobj, setThisOwn);