+//---------------------------------------------------------------------------
+
+// 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();
+}
+
+
+//---------------------------------------------------------------------------
+// Stuff used by OOR to find the right wxPython class type to return and to
+// build it.
+
+
+// The pointer type map is used when the "pointer" type name generated by SWIG
+// 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();
+    PyDict_SetItemString(wxPyPtrTypeMap,
+                         (char*)commonName,
+                         PyString_FromString((char*)ptrName));
+}
+
+
+
+PyObject* wxPyClassExists(const wxString& className) {
+
+    PyObject* item;
+    wxString  name(className);
+    char      buff[64];               // should always be big enough...
+
+    if (!className)
+        return NULL;
+
+    // Try the name as-is first
+    sprintf(buff, "%sPtr", (const char*)name.mbc_str());
+    PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
+
+    // if not found see if there is a mapped name for it
+    if ( ! classobj) {
+        if ((item = PyDict_GetItemString(wxPyPtrTypeMap, (char*)(const char*)name.mbc_str())) != NULL) {
+            name = wxString(PyString_AsString(item), *wxConvCurrent);
+            sprintf(buff, "%sPtr", (const char*)name.mbc_str());
+            classobj = PyDict_GetItemString(wxPython_dict, buff);
+        }
+    }
+
+    return classobj;  // returns NULL if not found
+}
+
+
+PyObject*  wxPyMake_wxObject(wxObject* source, bool checkEvtHandler) {
+    PyObject* target = NULL;
+    bool      isEvtHandler = FALSE;
+
+    if (source) {
+        // If it's derived from wxEvtHandler then there may
+        // already be a pointer to a Python object that we can use
+        // in the OOR data.
+        if (checkEvtHandler && wxIsKindOf(source, wxEvtHandler)) {
+            isEvtHandler = TRUE;
+            wxEvtHandler* eh = (wxEvtHandler*)source;
+            wxPyOORClientData* data = (wxPyOORClientData*)eh->GetClientObject();
+            if (data) {
+                target = data->m_obj;
+                Py_INCREF(target);
+            }
+        }
+
+        if (! target) {
+            // Otherwise make it the old fashioned way by making a
+            // new shadow object and putting this pointer in it.
+            wxClassInfo* info  = source->GetClassInfo();
+            wxString     name  = info->GetClassName();
+            PyObject*    klass = wxPyClassExists(name);
+            while (info && !klass) {
+                name = (wxChar*)info->GetBaseClassName1();
+                info = wxClassInfo::FindClass(name);
+                klass = wxPyClassExists(name);
+            }
+            if (info) {
+                target = wxPyConstructObject(source, name, klass, FALSE);
+                if (target && isEvtHandler)
+                    ((wxEvtHandler*)source)->SetClientObject(new wxPyOORClientData(target));
+            } else {
+                wxString msg(wxT("wxPython class not found for "));
+                msg += source->GetClassInfo()->GetClassName();
+                PyErr_SetString(PyExc_NameError, msg.mbc_str());
+                target = NULL;
+            }
+        }
+    } else {  // source was NULL so return None.
+        Py_INCREF(Py_None); target = Py_None;
+    }
+    return target;
+}
+
+
+PyObject*  wxPyMake_wxSizer(wxSizer* source) {
+    PyObject* target = NULL;
+
+    if (source && wxIsKindOf(source, wxSizer)) {
+        // If it's derived from wxSizer then there may
+        // already be a pointer to a Python object that we can use
+        // in the OOR data.
+        wxSizer* sz = (wxSizer*)source;
+        wxPyOORClientData* data = (wxPyOORClientData*)sz->GetClientObject();
+        if (data) {
+            target = data->m_obj;
+            Py_INCREF(target);
+        }
+    }
+    if (! target) {
+        target = wxPyMake_wxObject(source, FALSE);
+        if (target != Py_None)
+            ((wxSizer*)source)->SetClientObject(new wxPyOORClientData(target));
+    }
+    return target;
+}
+
+
+