X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3b7224dc830f33f997749bd4856a6c4312db8712..35095c028d472a2d0b9607a9430a468765a16e3f:/wxPython/src/helpers.cpp diff --git a/wxPython/src/helpers.cpp b/wxPython/src/helpers.cpp index 24d16eb352..c64bcf30b4 100644 --- a/wxPython/src/helpers.cpp +++ b/wxPython/src/helpers.cpp @@ -359,15 +359,23 @@ void wxPyApp::_BootstrapApp() // The stock objects were all NULL when they were loaded into // SWIG generated proxies, so re-init those now... - wxPy_ReinitStockObjects(False); + wxPy_ReinitStockObjects(3); // It's now ok to generate exceptions for assertion errors. wxPythonApp->SetStartupComplete(True); // Call the Python wxApp's OnInit function if (wxPyCBH_findCallback(m_myInst, "OnInit")) { - retval = wxPyCBH_callCallbackObj(m_myInst, Py_BuildValue("()")); - pyint = PyNumber_Int(retval); + + PyObject* method = m_myInst.GetLastFound(); + PyObject* argTuple = PyTuple_New(0); + retval = PyEval_CallObject(method, argTuple); + Py_DECREF(argTuple); + Py_DECREF(method); + if (retval == NULL) + goto error; + + pyint = PyNumber_Int(retval); if (! pyint) { PyErr_SetString(PyExc_TypeError, "OnInit should return a boolean value"); goto error; @@ -464,7 +472,7 @@ void __wxPyPreStart(PyObject* moduleDict) wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "wxPython"); // Init the stock objects to a non-NULL value so SWIG doesn't create them as None - wxPy_ReinitStockObjects(True); + wxPy_ReinitStockObjects(1); } @@ -556,33 +564,86 @@ bool wxPySwigInstance_Check(PyObject* obj) { //--------------------------------------------------------------------------- -// The stock objects are no longer created when the wxc module is imported, but -// only after the app object has been created. This function will be called before -// OnInit is called so we can hack the new pointer values into the obj.this attributes. +// The stock objects are no longer created when the wxc module is imported, +// but only after the app object has been created. The +// wxPy_ReinitStockObjects function will be called 3 times to pass the stock +// objects though various stages of evolution: +// +// pass 1: Set all the pointers to a non-NULL value so the Python proxy +// object will be created (otherwise it will just use None.) +// +// pass 2: After the module has been imported and the python proxys have +// been created, then set the __class__ to be _wxPyUnbornObject so +// it will catch any access to the object and will raise an exception. +// +// pass 3: Finally, from OnInit patch things up so the stock objects can +// be used. + + +PyObject* __wxPyFixStockObjects(PyObject* /* self */, PyObject* args) +{ + wxPy_ReinitStockObjects(2); + RETURN_NONE(); +} + + +static void rsoPass2(const char* name) +{ + static PyObject* unbornObjectClass = NULL; + PyObject* obj; + + if (unbornObjectClass == NULL) { + unbornObjectClass = PyDict_GetItemString(wxPython_dict, "_wxPyUnbornObject"); + Py_INCREF(unbornObjectClass); + } + + // Find the object instance + obj = PyDict_GetItemString(wxPython_dict, (char*)dropwx(name)); + wxCHECK_RET(obj != NULL, wxT("Unable to find stock object")); + wxCHECK_RET(wxPySwigInstance_Check(obj), wxT("Not a swig instance")); -void wxPy_ReinitStockObjects(bool init) + // Change its class + PyObject_SetAttrString(obj, "__class__", unbornObjectClass); + +} + +static void rsoPass3(const char* name, const char* classname, void* ptr) { PyObject* obj; + PyObject* classobj; PyObject* ptrobj; + // Find the object instance + obj = PyDict_GetItemString(wxPython_dict, (char*)dropwx(name)); + wxCHECK_RET(obj != NULL, wxT("Unable to find stock object")); + wxCHECK_RET(wxPySwigInstance_Check(obj), wxT("Not a swig instance")); + + // Find the class object and put it back in the instance + classobj = PyDict_GetItemString(wxPython_dict, (char*)dropwx(classname)); + wxCHECK_RET(classobj != NULL, wxT("Unable to find stock class object")); + PyObject_SetAttrString(obj, "__class__", classobj); + + // Rebuild the .this swigified pointer with the new value of the C++ pointer + ptrobj = wxPyMakeSwigPtr(ptr, wxString(classname, *wxConvCurrent)); + PyObject_SetAttrString(obj, "this", ptrobj); + Py_DECREF(ptrobj); +} + + + +void wxPy_ReinitStockObjects(int pass) +{ #define REINITOBJ(name, classname) \ - if ( init ) { name = (classname*)0xC0C0C0C0; } else { \ - obj = PyDict_GetItemString(wxPython_dict, dropwx(#name)); \ - wxCHECK_RET(obj != NULL, wxT("Unable to find stock object for " #name)) \ - wxCHECK_RET(wxPySwigInstance_Check(obj), wxT("Not a swig instance: " #name)); \ - ptrobj = wxPyMakeSwigPtr((void*)name, wxT(#classname)); \ - PyObject_SetAttrString(obj, "this", ptrobj); \ - Py_DECREF(ptrobj); } + if (pass == 1) { name = (classname*)0xC0C0C0C0; } \ + else if (pass == 2) { rsoPass2(#name); } \ + else if (pass == 3) { rsoPass3(#name, #classname, (void*)name); } + #define REINITOBJ2(name, classname) \ - if ( init ) { } else { \ - obj = PyDict_GetItemString(wxPython_dict, dropwx(#name)); \ - wxCHECK_RET(obj != NULL, wxT("Unable to find stock object for " #name)) \ - wxCHECK_RET(wxPySwigInstance_Check(obj), wxT("Not a swig instance: " #name)); \ - ptrobj = wxPyMakeSwigPtr((void*)&name, wxT(#classname)); \ - PyObject_SetAttrString(obj, "this", ptrobj); \ - Py_DECREF(ptrobj); } + if (pass == 1) { } \ + else if (pass == 2) { rsoPass2(#name); } \ + else if (pass == 3) { rsoPass3(#name, #classname, (void*)&name); } REINITOBJ(wxNORMAL_FONT, wxFont); @@ -1447,7 +1508,7 @@ int wxPyCallbackHelper::callCallback(PyObject* argTuple) const { } // Invoke the Python callable object, returning the raw PyObject return -// value. Caller should DECREF the return value and also call PyEval_SaveThread. +// value. Caller should DECREF the return value and also manage the GIL. PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) const { PyObject* result;