+//---------------------------------------------------------------------------
+
+// The stock objects are no longer created when the wxc module is imported, but
+// only after the app object has been created.  This function will be called before
+// OnInit is called so we can hack the new pointer values into the obj.this attributes.
+
+void wxPy_ReinitStockObjects()
+{
+    char ptrbuf[128];
+    PyObject* obj;
+    PyObject* ptrobj;
+
+
+
+#define REINITOBJ(name, type) \
+    obj = PyDict_GetItemString(wxPython_dict, #name); \
+    wxASSERT_MSG(obj != NULL, wxT("Unable to find stock object for " #name)); \
+    SWIG_MakePtr(ptrbuf, (char *) name, "_" #type "_p"); \
+    ptrobj = PyString_FromString(ptrbuf); \
+    PyObject_SetAttrString(obj, "this", ptrobj); \
+    Py_DECREF(ptrobj)
+
+#define REINITOBJ2(name, type) \
+    obj = PyDict_GetItemString(wxPython_dict, #name); \
+    wxASSERT_MSG(obj != NULL, wxT("Unable to find stock object for " #name)); \
+    SWIG_MakePtr(ptrbuf, (char *) &name, "_" #type "_p"); \
+    ptrobj = PyString_FromString(ptrbuf); \
+    PyObject_SetAttrString(obj, "this", ptrobj); \
+    Py_DECREF(ptrobj)
+
+
+    REINITOBJ(wxNORMAL_FONT, wxFont);
+    REINITOBJ(wxSMALL_FONT, wxFont);
+    REINITOBJ(wxITALIC_FONT, wxFont);
+    REINITOBJ(wxSWISS_FONT, wxFont);
+
+    REINITOBJ(wxRED_PEN, wxPen);
+    REINITOBJ(wxCYAN_PEN, wxPen);
+    REINITOBJ(wxGREEN_PEN, wxPen);
+    REINITOBJ(wxBLACK_PEN, wxPen);
+    REINITOBJ(wxWHITE_PEN, wxPen);
+    REINITOBJ(wxTRANSPARENT_PEN, wxPen);
+    REINITOBJ(wxBLACK_DASHED_PEN, wxPen);
+    REINITOBJ(wxGREY_PEN, wxPen);
+    REINITOBJ(wxMEDIUM_GREY_PEN, wxPen);
+    REINITOBJ(wxLIGHT_GREY_PEN, wxPen);
+
+    REINITOBJ(wxBLUE_BRUSH, wxBrush);
+    REINITOBJ(wxGREEN_BRUSH, wxBrush);
+    REINITOBJ(wxWHITE_BRUSH, wxBrush);
+    REINITOBJ(wxBLACK_BRUSH, wxBrush);
+    REINITOBJ(wxTRANSPARENT_BRUSH, wxBrush);
+    REINITOBJ(wxCYAN_BRUSH, wxBrush);
+    REINITOBJ(wxRED_BRUSH, wxBrush);
+    REINITOBJ(wxGREY_BRUSH, wxBrush);
+    REINITOBJ(wxMEDIUM_GREY_BRUSH, wxBrush);
+    REINITOBJ(wxLIGHT_GREY_BRUSH, wxBrush);
+
+    REINITOBJ(wxBLACK, wxColour);
+    REINITOBJ(wxWHITE, wxColour);
+    REINITOBJ(wxRED, wxColour);
+    REINITOBJ(wxBLUE, wxColour);
+    REINITOBJ(wxGREEN, wxColour);
+    REINITOBJ(wxCYAN, wxColour);
+    REINITOBJ(wxLIGHT_GREY, wxColour);
+
+    REINITOBJ(wxSTANDARD_CURSOR, wxCursor);
+    REINITOBJ(wxHOURGLASS_CURSOR, wxCursor);
+    REINITOBJ(wxCROSS_CURSOR, wxCursor);
+
+    REINITOBJ2(wxNullBitmap, wxBitmap);
+    REINITOBJ2(wxNullIcon, wxIcon);
+    REINITOBJ2(wxNullCursor, wxCursor);
+    REINITOBJ2(wxNullPen, wxPen);
+    REINITOBJ2(wxNullBrush, wxBrush);
+    REINITOBJ2(wxNullPalette, wxPalette);
+    REINITOBJ2(wxNullFont, wxFont);
+    REINITOBJ2(wxNullColour, wxColour);
+
+    REINITOBJ(wxTheFontList, wxFontList);
+    REINITOBJ(wxThePenList, wxPenList);
+    REINITOBJ(wxTheBrushList, wxBrushList);
+    REINITOBJ(wxTheColourDatabase, wxColourDatabase);
+
+
+    REINITOBJ(wxTheClipboard, wxClipboard);
+    REINITOBJ(wxTheMimeTypesManager, wxMimeTypesManager);
+    REINITOBJ2(wxDefaultValidator, wxValidator);
+    REINITOBJ2(wxNullImage, wxImage);
+    REINITOBJ2(wxNullAcceleratorTable, wxAcceleratorTable);
+
+#undef REINITOBJ
+#undef REINITOBJ2
+}
+
+//---------------------------------------------------------------------------
+
+void wxPyClientData_dtor(wxPyClientData* self) {
+    if (! wxPyDoingCleanup) {           // Don't do it during cleanup as Python
+                                        // may have already garbage collected the object...
+        wxPyBeginBlockThreads();
+        Py_DECREF(self->m_obj);
+        wxPyEndBlockThreads();
+    }
+}
+
+void wxPyUserData_dtor(wxPyUserData* self) {
+    if (! wxPyDoingCleanup) {
+        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);
+    }
+
+
+    // Only if there is more than one reference to the object
+    if ( !wxPyDoingCleanup && self->m_obj->ob_refcnt > 1 ) {
+        wxASSERT_MSG(PyInstance_Check(self->m_obj), wxT("m_obj not an instance!?!?!"));
+
+        // Call __del__, if there is one.
+        PyObject* func = PyObject_GetAttrString(self->m_obj, "__del__");
+        if (func) {
+            PyObject* rv = PyObject_CallMethod(self->m_obj, "__del__", NULL);
+            Py_XDECREF(rv);
+            Py_DECREF(func);
+        }
+        if (PyErr_Occurred())
+            PyErr_Clear();      // just ignore it for now
+
+        // Clear the instance's dictionary
+        PyInstanceObject* inst = (PyInstanceObject*)self->m_obj;
+        PyDict_Clear(inst->in_dict);
+
+        // put the name of the old class into the instance, and then reset the
+        // class to be the dead class.
+        PyDict_SetItemString(inst->in_dict, "_name", inst->in_class->cl_name);
+        inst->in_class = (PyClassObject*)deadObjectClass;
+        Py_INCREF(deadObjectClass);
+    }
+
+    // m_obj is DECREF's in the base class dtor...
+    wxPyEndBlockThreads();
+}
+
+