X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3a0958b1657f6105b1efcf04032070143b87af80..c70fd24fa839a38e807685df7cd2ef48c1b53884:/wxPython/src/helpers.cpp diff --git a/wxPython/src/helpers.cpp b/wxPython/src/helpers.cpp index 131ed8b56d..e485a2f817 100644 --- a/wxPython/src/helpers.cpp +++ b/wxPython/src/helpers.cpp @@ -101,7 +101,8 @@ void WXDLLEXPORT wxEntryCleanup(); #ifdef WXP_WITH_THREAD -PyThreadState* wxPyEventThreadState = NULL; +//PyThreadState* wxPyEventThreadState = NULL; +PyInterpreterState* wxPyInterpreter = NULL; #endif @@ -117,7 +118,8 @@ void __wxPreStart() #ifdef WXP_WITH_THREAD PyEval_InitThreads(); - wxPyEventThreadState = PyThreadState_Get(); // PyThreadState_New(PyThreadState_Get()->interp); +// wxPyEventThreadState = PyThreadState_Get(); // PyThreadState_New(PyThreadState_Get()->interp); + wxPyInterpreter = PyThreadState_Get()->interp; #endif // Bail out if there is already windows created. This means that the @@ -288,24 +290,51 @@ PyObject* wxPyClassExists(const char* className) { PyObject* wxPyMake_wxObject(wxObject* source) { - PyObject* target; + PyObject* target = NULL; + bool isEvtHandler = FALSE; if (source) { - wxClassInfo* info = source->GetClassInfo(); - wxChar* name = (wxChar*)info->GetClassName(); - PyObject* klass = wxPyClassExists(name); - while (info && !klass) { - name = (wxChar*)info->GetBaseClassName1(); - info = wxClassInfo::FindClass(name); - klass = wxPyClassExists(name); + // If it's derived from wxEvtHandler then there may + // already be a pointer to a Python objec that we can use. + if (wxIsKindOf(source, wxEvtHandler)) { + wxEvtHandler* eh = (wxEvtHandler*)source; + wxPyClientData* data = (wxPyClientData*)eh->GetClientObject(); + if (data) { + target = data->m_obj; + Py_INCREF(target); + } } - if (info) { - target = wxPyConstructObject(source, name, klass, FALSE); - } else { - wxString msg("wxPython class not found for "); - msg += source->GetClassInfo()->GetClassName(); - PyErr_SetString(PyExc_NameError, msg.c_str()); - target = NULL; + else if (wxIsKindOf(source, wxSizer)) { + // wxSizers also track the original object + wxSizer* sz = (wxSizer*)source; + wxPyClientData* data = (wxPyClientData*)sz->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(); + wxChar* name = (wxChar*)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 wxPyClientData(target)); + } else { + wxString msg("wxPython class not found for "); + msg += source->GetClassInfo()->GetClassName(); + PyErr_SetString(PyExc_NameError, msg.c_str()); + target = NULL; + } } } else { // source was NULL so return None. Py_INCREF(Py_None); target = Py_None; @@ -313,6 +342,7 @@ PyObject* wxPyMake_wxObject(wxObject* source) { return target; } + //--------------------------------------------------------------------------- PyObject* wxPyConstructObject(void* ptr, @@ -374,41 +404,34 @@ PyObject* wxPyConstructObject(void* ptr, //--------------------------------------------------------------------------- -static PyThreadState* myPyThreadState_Get() { - PyThreadState* current; - current = PyThreadState_Swap(NULL); - PyThreadState_Swap(current); - return current; -} - -bool wxPyRestoreThread() { - // NOTE: The Python API docs state that if a thread already has the - // interpreter lock and calls PyEval_RestoreThread again a deadlock - // occurs, so I put in this code as a guard condition since there are - // many possibilites for nested events and callbacks in wxPython. If - // The current thread is our thread, then we can assume that we - // already have the lock. (I hope!) - // +wxPyTState* wxPyBeginBlockThreads() { + wxPyTState* state = NULL; #ifdef WXP_WITH_THREAD - if (wxPyEventThreadState != myPyThreadState_Get()) { - PyEval_AcquireThread(wxPyEventThreadState); - return TRUE; + if (1) { // Can I check if I've already got the lock? + state = new wxPyTState; + PyEval_AcquireLock(); + state->newState = PyThreadState_New(wxPyInterpreter); + state->prevState = PyThreadState_Swap(state->newState); } - else #endif - return FALSE; + return state; } -void wxPySaveThread(bool doSave) { +void wxPyEndBlockThreads(wxPyTState* state) { #ifdef WXP_WITH_THREAD - if (doSave) { - PyEval_ReleaseThread(wxPyEventThreadState); + if (state) { + PyThreadState_Swap(state->prevState); + PyThreadState_Clear(state->newState); + PyEval_ReleaseLock(); + PyThreadState_Delete(state->newState); + delete state; } #endif } + //--------------------------------------------------------------------------- IMPLEMENT_ABSTRACT_CLASS(wxPyCallback, wxObject); @@ -424,9 +447,9 @@ wxPyCallback::wxPyCallback(const wxPyCallback& other) { } wxPyCallback::~wxPyCallback() { - bool doSave = wxPyRestoreThread(); + wxPyTState* state = wxPyBeginBlockThreads(); Py_DECREF(m_func); - wxPySaveThread(doSave); + wxPyEndBlockThreads(state); } @@ -440,7 +463,7 @@ void wxPyCallback::EventThunker(wxEvent& event) { PyObject* tuple; - bool doSave = wxPyRestoreThread(); + wxPyTState* state = wxPyBeginBlockThreads(); wxString className = event.GetClassInfo()->GetClassName(); if (className == "wxPyEvent") @@ -460,7 +483,7 @@ void wxPyCallback::EventThunker(wxEvent& event) { } else { PyErr_Print(); } - wxPySaveThread(doSave); + wxPyEndBlockThreads(state); } @@ -545,7 +568,7 @@ PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) const { } -void wxPyCBH_setSelf(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref) { +void wxPyCBH_setCallbackInfo(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref) { cbh.setSelf(self, klass, incref); } @@ -563,17 +586,17 @@ PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTu void wxPyCBH_delete(wxPyCallbackHelper* cbh) { - bool doSave = wxPyRestoreThread(); if (cbh->m_incRef) { + wxPyTState* state = wxPyBeginBlockThreads(); Py_XDECREF(cbh->m_self); Py_XDECREF(cbh->m_class); + wxPyEndBlockThreads(state); } - wxPySaveThread(doSave); } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- -// These classes can be derived from in Python and passed through the event +// These event classes can be derived from in Python and passed through the event // system without losing anything. They do this by keeping a reference to // themselves and some special case handling in wxPyCallback::EventThunker. @@ -585,14 +608,14 @@ wxPyEvtSelfRef::wxPyEvtSelfRef() { } wxPyEvtSelfRef::~wxPyEvtSelfRef() { - bool doSave = wxPyRestoreThread(); + wxPyTState* state = wxPyBeginBlockThreads(); if (m_cloned) Py_DECREF(m_self); - wxPySaveThread(doSave); + wxPyEndBlockThreads(state); } void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) { - bool doSave = wxPyRestoreThread(); + wxPyTState* state = wxPyBeginBlockThreads(); if (m_cloned) Py_DECREF(m_self); m_self = self; @@ -600,7 +623,7 @@ void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) { Py_INCREF(m_self); m_cloned = TRUE; } - wxPySaveThread(doSave); + wxPyEndBlockThreads(state); } PyObject* wxPyEvtSelfRef::GetSelf() const { @@ -653,9 +676,9 @@ wxPyTimer::wxPyTimer(PyObject* callback) { } wxPyTimer::~wxPyTimer() { - bool doSave = wxPyRestoreThread(); + wxPyTState* state = wxPyBeginBlockThreads(); Py_DECREF(func); - wxPySaveThread(doSave); + wxPyEndBlockThreads(state); } void wxPyTimer::Notify() { @@ -663,7 +686,7 @@ void wxPyTimer::Notify() { wxTimer::Notify(); } else { - bool doSave = wxPyRestoreThread(); + wxPyTState* state = wxPyBeginBlockThreads(); PyObject* result; PyObject* args = Py_BuildValue("()"); @@ -677,7 +700,7 @@ void wxPyTimer::Notify() { PyErr_Print(); } - wxPySaveThread(doSave); + wxPyEndBlockThreads(state); } } @@ -693,7 +716,7 @@ PyObject* wxPy_ConvertList(wxListBase* list, const char* className) { wxObject* wxObj; wxNode* node = list->First(); - bool doSave = wxPyRestoreThread(); + wxPyTState* state = wxPyBeginBlockThreads(); pyList = PyList_New(0); while (node) { wxObj = node->Data(); @@ -701,7 +724,7 @@ PyObject* wxPy_ConvertList(wxListBase* list, const char* className) { PyList_Append(pyList, pyObj); node = node->Next(); } - wxPySaveThread(doSave); + wxPyEndBlockThreads(state); return pyList; } @@ -847,23 +870,19 @@ static inline bool wxPointFromObjects(PyObject* o1, PyObject* o2, wxPoint* point } -#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)) -#endif - wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) { // Putting all of the declarations here allows // us to put the error handling all in one place. int x; wxPoint* temp; PyObject *o, *o1, *o2; - int isFast = PyList_Check(source) || PyTuple_Check(source); + bool isFast = PyList_Check(source) || PyTuple_Check(source); - // The length of the sequence is returned in count. if (!PySequence_Check(source)) { goto error0; } + + // The length of the sequence is returned in count. *count = PySequence_Length(source); if (*count < 0) { goto error0; @@ -980,11 +999,24 @@ wxString* wxString_LIST_helper(PyObject* source) { } for (int x=0; x= 1009 + if (! PyString_Check(o) && ! PyUnicode_Check(o)) { + PyErr_SetString(PyExc_TypeError, "Expected a list of string or unicode objects."); + return NULL; + } + + char* buff; + int length; + if (PyString_AsStringAndSize(o, &buff, &length) == -1) + return NULL; + temp[x] = wxString(buff, length); +#else if (! PyString_Check(o)) { PyErr_SetString(PyExc_TypeError, "Expected a list of strings."); return NULL; } temp[x] = PyString_AsString(o); +#endif } return temp; } @@ -1026,6 +1058,99 @@ wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) { } +wxPen** wxPen_LIST_helper(PyObject* source) { + if (!PyList_Check(source)) { + PyErr_SetString(PyExc_TypeError, "Expected a list object."); + return NULL; + } + int count = PyList_Size(source); + wxPen** temp = new wxPen*[count]; + if (!temp) { + PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array"); + return NULL; + } + for (int x=0; x