]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/src/helpers.cpp
A few little tweaks, reswigged code for wxMac
[wxWidgets.git] / wxPython / src / helpers.cpp
index aa48fa7128f22dd8fe81de5776e7f626214e1bd0..4188b1ebb9dedca6adbd4bc21dfbaa85ab17a58c 100644 (file)
@@ -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
@@ -79,8 +80,11 @@ BOOL WINAPI DllMain(
     LPVOID      lpvReserved  // reserved
    )
 {
-    wxSetInstance(hinstDLL);
-    return 1;
+    // If wxPython is embedded in another wxWindows app then
+    // the inatance has already been set.
+    if (! wxGetInstance())
+        wxSetInstance(hinstDLL);
+    return TRUE;
 }
 #endif
 
@@ -178,12 +182,15 @@ void __wxPreStart()
     wxPyTMutex = new wxMutex;
 #endif
 
-    // Bail out if there is already windows created.  This means that the
+    wxApp::CheckBuildOptions(wxBuildOptions());
+
+    // Bail out if there is already a wxApp created.  This means that the
     // toolkit has already been initialized, as in embedding wxPython in
-    // a C++ wxWindows app.
-    if (wxTopLevelWindows.Number() > 0)
+    // a C++ wxWindows app, so we don't need to call wxEntryStart.
+    if (wxTheApp != NULL) {
         return;
-
+    }
+    wxPyDoCleanup = TRUE;
 
     int argc = 0;
     char** argv = NULL;
@@ -280,7 +287,8 @@ PyObject* __wxStart(PyObject* /* self */, PyObject* args)
 
 
 void __wxCleanup() {
-    wxEntryCleanup();
+    if (wxPyDoCleanup)
+        wxEntryCleanup();
 #ifdef WXP_WITH_THREAD
     delete wxPyTMutex;
     wxPyTMutex = NULL;
@@ -295,6 +303,7 @@ void __wxCleanup() {
 static PyObject* wxPython_dict = NULL;
 static PyObject* wxPyPtrTypeMap = NULL;
 
+
 PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args)
 {
 
@@ -334,6 +343,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 +399,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 +435,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 +456,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 +479,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 +488,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;
 }
@@ -476,8 +532,6 @@ PyObject* wxPyConstructObject(void* ptr,
 PyObject* wxPyConstructObject(void* ptr,
                               const wxString& className,
                               int setThisOwn) {
-    PyObject* obj;
-
     if (!ptr) {
         Py_INCREF(Py_None);
         return Py_None;
@@ -490,12 +544,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);