]> git.saurik.com Git - wxWidgets.git/commitdiff
A little black magic... When the C++ object (for a window or
authorRobin Dunn <robin@alldunn.com>
Tue, 9 Apr 2002 22:01:45 +0000 (22:01 +0000)
committerRobin Dunn <robin@alldunn.com>
Tue, 9 Apr 2002 22:01:45 +0000 (22:01 +0000)
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

18 files changed:
wxPython/contrib/ogl/ogl.cpp
wxPython/contrib/ogl/ogl.i
wxPython/contrib/ogl/oglbasic.cpp
wxPython/contrib/ogl/oglbasic.i
wxPython/src/_extras.py
wxPython/src/export.h
wxPython/src/helpers.cpp
wxPython/src/helpers.h
wxPython/src/msw/gdi.py
wxPython/src/msw/sizers.cpp
wxPython/src/msw/utils.cpp
wxPython/src/msw/windows.cpp
wxPython/src/msw/wx.cpp
wxPython/src/msw/wx.py
wxPython/src/sizers.i
wxPython/src/utils.i
wxPython/src/windows.i
wxPython/src/wx.i

index 9de0ddb93f3b1ad6889cda5fcbd914185605d0ab..3c74a41f61012dae2df035a54d413111a3e59148 100644 (file)
@@ -172,7 +172,7 @@ PyObject*  wxPyMake_wxShapeEvtHandler(wxShapeEvtHandler* source) {
         // already be a pointer to a Python object that we can use
         // in the OOR data.
         wxShapeEvtHandler* seh = (wxShapeEvtHandler*)source;
-        wxPyClientData* data = (wxPyClientData*)seh->GetClientObject();
+        wxPyOORClientData* data = (wxPyOORClientData*)seh->GetClientObject();
         if (data) {
             target = data->m_obj;
             Py_INCREF(target);
@@ -181,7 +181,7 @@ PyObject*  wxPyMake_wxShapeEvtHandler(wxShapeEvtHandler* source) {
     if (! target) {
         target = wxPyMake_wxObject2(source, FALSE);
         if (target != Py_None)
-            ((wxShapeEvtHandler*)source)->SetClientObject(new wxPyClientData(target));
+            ((wxShapeEvtHandler*)source)->SetClientObject(new wxPyOORClientData(target));
     }
     return target;
 }
index bdae01992f281cda8eb0ac4ee0a2038055e6adab..dfa1a664a29c7dadd325b65250a2816cce63d936 100644 (file)
@@ -221,7 +221,7 @@ PyObject*  wxPyMake_wxShapeEvtHandler(wxShapeEvtHandler* source) {
         // already be a pointer to a Python object that we can use
         // in the OOR data.
         wxShapeEvtHandler* seh = (wxShapeEvtHandler*)source;
-        wxPyClientData* data = (wxPyClientData*)seh->GetClientObject();
+        wxPyOORClientData* data = (wxPyOORClientData*)seh->GetClientObject();
         if (data) {
             target = data->m_obj;
             Py_INCREF(target);
@@ -230,7 +230,7 @@ PyObject*  wxPyMake_wxShapeEvtHandler(wxShapeEvtHandler* source) {
     if (! target) {
         target = wxPyMake_wxObject2(source, FALSE);
         if (target != Py_None)
-            ((wxShapeEvtHandler*)source)->SetClientObject(new wxPyClientData(target));
+            ((wxShapeEvtHandler*)source)->SetClientObject(new wxPyOORClientData(target));
     }
     return target;
 }
index 482538b0b236c513cba76e1e2b75a1243d264400..c0bc910213d854833d20d66f649601dcf077d0f8 100644 (file)
@@ -1249,7 +1249,7 @@ static PyObject *_wrap_wxPyShapeEvtHandler_Destroy(PyObject *self, PyObject *arg
 }
 
 static void  wxPyShapeEvtHandler__setOORInfo(wxPyShapeEvtHandler *self,PyObject * _self) {
-            self->SetClientObject(new wxPyClientData(_self));
+            self->SetClientObject(new wxPyOORClientData(_self));
         }
 static PyObject *_wrap_wxPyShapeEvtHandler__setOORInfo(PyObject *self, PyObject *args, PyObject *kwargs) {
     PyObject * _resultobj;
index c1f6c8301468344739409936a7f06c4a121e4f2a..23380890165032b070978e1db7ccda8f6180f6f5 100644 (file)
@@ -99,7 +99,7 @@ public:
     %addmethods { void Destroy() { delete self; } }
     %addmethods {
         void _setOORInfo(PyObject* _self) {
-            self->SetClientObject(new wxPyClientData(_self));
+            self->SetClientObject(new wxPyOORClientData(_self));
         }
     }
 
index 708d1fd586d96d9b59afc4c287d1800d6ad19b7c..866ab98cf77522bdcbc559111cd06925fa73e42f 100644 (file)
@@ -647,6 +647,26 @@ def wxPyTypeCast(obj, typeStr):
     return theObj
 
 
+#----------------------------------------------------------------------------
+
+
+class _wxPyDeadObject:
+    """
+    Instances of wx objects that are OOR capable will have their __class__
+    changed to this class when the C++ object is deleted.  This should help
+    prevent crashes due to referencing a bogus C++ pointer.
+    """
+    def __repr__( self ):
+        if not hasattr(self, "_name"):
+            self._name = "[unknown]"
+        return 'wxPython wrapper for deleted %s object!!! Programming logic error' % self._name
+
+    def __getattr__( self, *args ):
+        if not hasattr(self, "_name"):
+            self._name = "[unknown]"
+        raise ValueError, 'Attempt to access attribute of a deleted %s object' % self._name
+
+
 #----------------------------------------------------------------------
 #----------------------------------------------------------------------
 
@@ -763,10 +783,10 @@ class wxPyWidgetTester(wxApp):
         self.frame.Show(true)
 
 #----------------------------------------------------------------------------
-# DO NOT hold any other references to this object.  This is how we know when
-# to cleanup system resources that wxWin is holding.  When this module is
-# unloaded, the refcount on __cleanMeUp goes to zero and it calls the
-# wxApp_CleanUp function.
+# DO NOT hold any other references to this object.  This is how we
+# know when to cleanup system resources that wxWin is holding.  When
+# the sys module is unloaded, the refcount on sys.__wxPythonCleanup
+# goes to zero and it calls the wxApp_CleanUp function.
 
 class __wxPyCleanup:
     def __init__(self):
index c0b9c25a671a0c22b34b37915cf95f3ec8bcdc9b..a38a1c7a6799cbc96811ce4f93faad483c63d676 100644 (file)
@@ -74,6 +74,9 @@ static void wxPyCoreAPI_IMPORT() {
 #define wxArrayString2PyList_helper(a)      (wxPyCoreAPIPtr->p_wxArrayString2PyList_helper(a))
 #define wxArrayInt2PyList_helper(a)         (wxPyCoreAPIPtr->p_wxArrayInt2PyList_helper(a))
 
+#define wxPyClientData_dtor(a)              (wxPyCoreAPIPtr->p_wxPyClientData_dtor(a))
+#define wxPyUserData_dtor(a)                (wxPyCoreAPIPtr->p_wxPyUserData_dtor(a))
+#define wxPyOORClientData_dtor(a)           (wxPyCoreAPIPtr->p_wxPyOORClientData_dtor(a))
 
 // This one is special.  It's the first function called in SWIG generated
 // modules, so we'll use it to also import the API.
index aa48fa7128f22dd8fe81de5776e7f626214e1bd0..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;
 }
index 50ba51088324956ef05ec755b0bbc29819f6fa92..4ec75ec53432b78799685b2e20cf6c6de778737e 100644 (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,11 +271,69 @@ 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 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
-static wxPyCoreAPI* wxPyCoreAPIPtr = NULL;  // Each module needs one, but may not use it.
+        wxPyCoreAPIPtr->p_wxPyOORClientData_dtor(this);
+#else
+        wxPyOORClientData_dtor(this);
 #endif
+    }
+};
 
 //---------------------------------------------------------------------------
 // This class holds an instance of a Python Shadow Class object and assists
@@ -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
index eda13bc5eca978c642ac79d6b14bbcd609b476b4..9ab2cec48ff89a0bdd4c6e3d553fe587c09af31b 100644 (file)
@@ -866,14 +866,14 @@ class wxBufferedDC(wxBufferedDCPtr):
     def __init__(self,*_args,**_kwargs):
         self.this = apply(gdic.new_wxBufferedDC,_args,_kwargs)
         self.thisown = 1
-        self._dc = _args[0] # save a ref so it won't be deleted before self
+        self._dc = _args[0] # save a ref so the other dc won't be deleted before self
 
 
 
 def wxBufferedDCInternalBuffer(*_args,**_kwargs):
     val = wxBufferedDCPtr(apply(gdic.new_wxBufferedDCInternalBuffer,_args,_kwargs))
     val.thisown = 1
-    val._dc = _args[0] # save a ref so it won't be deleted before self
+    val._dc = _args[0] # save a ref so the other dc won't be deleted before self
     return val
 
 
index 5bddf40caf288982c2a61676109152f913cec855..bc740b04cf0bf2eafb21e86840c1d4569ace8996 100644 (file)
@@ -860,7 +860,7 @@ static void *SwigwxSizerTowxObject(void *ptr) {
 }
 
 static void  wxSizer__setOORInfo(wxSizer *self,PyObject * _self) {
-            self->SetClientObject(new wxPyClientData(_self));
+            self->SetClientObject(new wxPyOORClientData(_self));
         }
 static PyObject *_wrap_wxSizer__setOORInfo(PyObject *self, PyObject *args, PyObject *kwargs) {
     PyObject * _resultobj;
index 4475235a09d864be9c8736b248b66e0b2bd6100e..657cefed9cbacd75078c61f6c1cc4cbfdfddfc02 100644 (file)
@@ -55,14 +55,13 @@ extern PyObject *SWIG_newvarlink(void);
 
 #define SWIG_name    "utilsc"
 
-#include "export.h"
+#include "helpers.h"
 #include <wx/config.h>
 #include <wx/fileconf.h>
 #include <wx/datetime.h>
 
     // Put some wx default wxChar* values into wxStrings.
-    static const wxChar* wxDateFormatStr = wxT("sashWindow");
-    DECLARE_DEF_STRING(DateFormatStr);
+    DECLARE_DEF_STRING2(DateFormatStr, wxT("sashWindow"));
     static const wxString wxPyEmptyString(wxT(""));
 
 
index 228779aa2bf652d4db47f067ea72b8e3ff251135..93f30a99afd805d6f17147c92d456a5208a47590 100644 (file)
@@ -548,7 +548,7 @@ static PyObject *_wrap_wxEvtHandler_Disconnect(PyObject *self, PyObject *args, P
 }
 
 static void  wxEvtHandler__setOORInfo(wxEvtHandler *self,PyObject * _self) {
-            self->SetClientObject(new wxPyClientData(_self));
+            self->SetClientObject(new wxPyOORClientData(_self));
         }
 static PyObject *_wrap_wxEvtHandler__setOORInfo(PyObject *self, PyObject *args, PyObject *kwargs) {
     PyObject * _resultobj;
index fe8e6ac8c3f063d3902c16805cb65b9e0b3c313f..7d73f40df89169b60477104fd8d138fab984ddf3 100644 (file)
@@ -677,7 +677,11 @@ static wxPyCoreAPI API = {
     wxPyMake_wxSizer,
     wxPyPtrTypeMap_Add,
     wxArrayString2PyList_helper,
-    wxArrayInt2PyList_helper
+    wxArrayInt2PyList_helper,
+
+    wxPyClientData_dtor,
+    wxPyUserData_dtor,
+    wxPyOORClientData_dtor
 };
 
 
index 2cc382ee356668132513f42469bac7d9711d388e..35e1ba43d29fddaed3d77539f1162cbc8cd11c82 100644 (file)
@@ -1554,6 +1554,26 @@ def wxPyTypeCast(obj, typeStr):
     return theObj
 
 
+#----------------------------------------------------------------------------
+
+
+class _wxPyDeadObject:
+    """
+    Instances of wx objects that are OOR capable will have their __class__
+    changed to this class when the C++ object is deleted.  This should help
+    prevent crashes due to referencing a bogus C++ pointer.
+    """
+    def __repr__( self ):
+        if not hasattr(self, "_name"):
+            self._name = "[unknown]"
+        return 'wxPython wrapper for deleted %s object!!! Programming logic error' % self._name
+
+    def __getattr__( self, *args ):
+        if not hasattr(self, "_name"):
+            self._name = "[unknown]"
+        raise ValueError, 'Attempt to access attribute of a deleted %s object' % self._name
+
+
 #----------------------------------------------------------------------
 #----------------------------------------------------------------------
 
@@ -1670,10 +1690,10 @@ class wxPyWidgetTester(wxApp):
         self.frame.Show(true)
 
 #----------------------------------------------------------------------------
-# DO NOT hold any other references to this object.  This is how we know when
-# to cleanup system resources that wxWin is holding.  When this module is
-# unloaded, the refcount on __cleanMeUp goes to zero and it calls the
-# wxApp_CleanUp function.
+# DO NOT hold any other references to this object.  This is how we
+# know when to cleanup system resources that wxWin is holding.  When
+# the sys module is unloaded, the refcount on sys.__wxPythonCleanup
+# goes to zero and it calls the wxApp_CleanUp function.
 
 class __wxPyCleanup:
     def __init__(self):
index a43993df98892c41f09336201582aa80ad3f083f..1e65076ff97466397be1a0e0400f1b922a6068d6 100644 (file)
@@ -97,7 +97,7 @@ public:
 
     %addmethods {
         void _setOORInfo(PyObject* _self) {
-            self->SetClientObject(new wxPyClientData(_self));
+            self->SetClientObject(new wxPyOORClientData(_self));
         }
     }
 
index ada7c8ad1137bc1a4f157ec81e37d18aaca7525c..24a33a10efdd2b9208fcb47f0875f91f472901f6 100644 (file)
@@ -14,7 +14,7 @@
 %module utils
 
 %{
-#include "export.h"
+#include "helpers.h"
 #include <wx/config.h>
 #include <wx/fileconf.h>
 #include <wx/datetime.h>
@@ -23,8 +23,7 @@
 //---------------------------------------------------------------------------
 %{
     // Put some wx default wxChar* values into wxStrings.
-    static const wxChar* wxDateFormatStr = wxT("sashWindow");
-    DECLARE_DEF_STRING(DateFormatStr);
+    DECLARE_DEF_STRING2(DateFormatStr, wxT("sashWindow"));
     static const wxString wxPyEmptyString(wxT(""));
 
 %}
index a79cea8664eb6b940f698c4ba032ac813505a7f7..10778765a6d495896814c1c8acf77e6089c5a40f 100644 (file)
@@ -87,7 +87,7 @@ public:
 
     %addmethods {
         void _setOORInfo(PyObject* _self) {
-            self->SetClientObject(new wxPyClientData(_self));
+            self->SetClientObject(new wxPyOORClientData(_self));
         }
     }
 };
index f51a623b6db84aa5df18c551815b5d77f6495b84..351c6e4bb1812c8c4f46d592f4e92c35f1b70029 100644 (file)
@@ -202,7 +202,11 @@ static wxPyCoreAPI API = {
     wxPyMake_wxSizer,
     wxPyPtrTypeMap_Add,
     wxArrayString2PyList_helper,
-    wxArrayInt2PyList_helper
+    wxArrayInt2PyList_helper,
+
+    wxPyClientData_dtor,
+    wxPyUserData_dtor,
+    wxPyOORClientData_dtor
 };