void WXDLLEXPORT wxEntryCleanup();
wxPyApp* wxPythonApp = NULL; // Global instance of application object
+bool wxPyDoCleanup = FALSE;
#ifdef WXP_WITH_THREAD
if (wxTopLevelWindows.Number() > 0)
return;
+ wxPyDoCleanup = TRUE;
int argc = 0;
char** argv = NULL;
void __wxCleanup() {
- wxEntryCleanup();
+ if (wxPyDoCleanup)
+ wxEntryCleanup();
#ifdef WXP_WITH_THREAD
delete wxPyTMutex;
wxPyTMutex = NULL;
static PyObject* wxPython_dict = NULL;
static PyObject* wxPyPtrTypeMap = NULL;
+
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
// 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();
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);
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;
// 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);
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;
}
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);
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;
}
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:
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;
}
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;
}
if (spec.GetChar(0) == '#' && spec.Length() == 7) { // It's #RRGGBB
long red, green, blue;
red = green = blue = 0;
-
spec.Mid(1,2).ToLong(&red, 16);
spec.Mid(3,2).ToLong(&green, 16);
spec.Mid(5,2).ToLong(&blue, 16);