]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/src/helpers.cpp
make wxArtProvider pure virtual (I was not so on
[wxWidgets.git] / wxPython / src / helpers.cpp
index 8d602244e0c5dd772c83afbc37e73a2823b20671..c3c52d2a6e0c76a81e4dfa23c85ea792996faaa1 100644 (file)
@@ -295,6 +295,7 @@ void __wxCleanup() {
 static PyObject* wxPython_dict = NULL;
 static PyObject* wxPyPtrTypeMap = NULL;
 
+
 PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args)
 {
 
@@ -334,6 +335,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 +391,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 +427,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 +448,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 +471,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 +480,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;
 }
@@ -1777,7 +1825,14 @@ bool wxSize_helper(PyObject* source, wxSize** obj) {
     else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
         PyObject* o1 = PySequence_GetItem(source, 0);
         PyObject* o2 = PySequence_GetItem(source, 1);
+        if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
+            Py_DECREF(o1);
+            Py_DECREF(o2);
+            goto error;
+        }
         **obj = wxSize(PyInt_AsLong(o1), PyInt_AsLong(o2));
+        Py_DECREF(o1);
+        Py_DECREF(o2);
         return TRUE;
     }
 
@@ -1800,15 +1855,15 @@ bool wxPoint_helper(PyObject* source, wxPoint** obj) {
     if (PySequence_Check(source) && PySequence_Length(source) == 2) {
         PyObject* o1 = PySequence_GetItem(source, 0);
         PyObject* o2 = PySequence_GetItem(source, 1);
-                // This should really check for integers, not numbers -- but that would break code.
-                if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
-                        Py_DECREF(o1);
-                    Py_DECREF(o2);
-                        goto error;
-                }
-                **obj = wxPoint(PyInt_AsLong(o1), PyInt_AsLong(o2));
-                Py_DECREF(o1);
-                Py_DECREF(o2);
+        // This should really check for integers, not numbers -- but that would break code.
+        if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
+            Py_DECREF(o1);
+            Py_DECREF(o2);
+            goto error;
+        }
+        **obj = wxPoint(PyInt_AsLong(o1), PyInt_AsLong(o2));
+        Py_DECREF(o1);
+        Py_DECREF(o2);
         return TRUE;
     }
  error:
@@ -1832,7 +1887,14 @@ bool wxRealPoint_helper(PyObject* source, wxRealPoint** obj) {
     else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
         PyObject* o1 = PySequence_GetItem(source, 0);
         PyObject* o2 = PySequence_GetItem(source, 1);
+        if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
+            Py_DECREF(o1);
+            Py_DECREF(o2);
+            goto error;
+        }
         **obj = wxRealPoint(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2));
+        Py_DECREF(o1);
+        Py_DECREF(o2);
         return TRUE;
     }
 
@@ -1860,8 +1922,20 @@ bool wxRect_helper(PyObject* source, wxRect** obj) {
         PyObject* o2 = PySequence_GetItem(source, 1);
         PyObject* o3 = PySequence_GetItem(source, 2);
         PyObject* o4 = PySequence_GetItem(source, 3);
+        if (!PyNumber_Check(o1) || !PyNumber_Check(o2) ||
+            !PyNumber_Check(o3) || !PyNumber_Check(o4)) {
+            Py_DECREF(o1);
+            Py_DECREF(o2);
+            Py_DECREF(o3);
+            Py_DECREF(o4);
+            goto error;
+        }
         **obj = wxRect(PyInt_AsLong(o1), PyInt_AsLong(o2),
-                     PyInt_AsLong(o3), PyInt_AsLong(o4));
+                       PyInt_AsLong(o3), PyInt_AsLong(o4));
+        Py_DECREF(o1);
+        Py_DECREF(o2);
+        Py_DECREF(o3);
+        Py_DECREF(o4);
         return TRUE;
     }