Reworked how stock objects are initialized. They now have an
alternate __class__ until the App is initialized so they will raise an exception if anybody tries to use them before the C++ object has been created. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@24899 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -92,6 +92,7 @@ const bool False = false;
|
|||||||
void __wxPyPreStart(PyObject*);
|
void __wxPyPreStart(PyObject*);
|
||||||
void __wxPyCleanup();
|
void __wxPyCleanup();
|
||||||
PyObject* __wxPySetDictionary(PyObject*, PyObject* args);
|
PyObject* __wxPySetDictionary(PyObject*, PyObject* args);
|
||||||
|
PyObject* __wxPyFixStockObjects(PyObject*, PyObject* args);
|
||||||
|
|
||||||
|
|
||||||
void wxPyEventThunker(wxObject*, wxEvent& event);
|
void wxPyEventThunker(wxObject*, wxEvent& event);
|
||||||
@@ -116,7 +117,7 @@ void wxPyPtrTypeMap_Add(const char* commonName, const char* ptrName);
|
|||||||
PyObject* wxPy_ConvertList(wxListBase* list);
|
PyObject* wxPy_ConvertList(wxListBase* list);
|
||||||
long wxPyGetWinHandle(wxWindow* win);
|
long wxPyGetWinHandle(wxWindow* win);
|
||||||
|
|
||||||
void wxPy_ReinitStockObjects(bool init);
|
void wxPy_ReinitStockObjects(int pass);
|
||||||
|
|
||||||
bool wxPyInstance_Check(PyObject* obj);
|
bool wxPyInstance_Check(PyObject* obj);
|
||||||
bool wxPySwigInstance_Check(PyObject* obj);
|
bool wxPySwigInstance_Check(PyObject* obj);
|
||||||
|
@@ -33,7 +33,6 @@ if RELEASE_VERSION != _core.RELEASE_VERSION:
|
|||||||
class PyDeadObjectError(AttributeError):
|
class PyDeadObjectError(AttributeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class _wxPyDeadObject(object):
|
class _wxPyDeadObject(object):
|
||||||
"""
|
"""
|
||||||
Instances of wx objects that are OOR capable will have their __class__
|
Instances of wx objects that are OOR capable will have their __class__
|
||||||
@@ -43,15 +42,46 @@ class _wxPyDeadObject(object):
|
|||||||
reprStr = "wxPython wrapper for DELETED %s object! (The C++ object no longer exists.)"
|
reprStr = "wxPython wrapper for DELETED %s object! (The C++ object no longer exists.)"
|
||||||
attrStr = "The C++ part of the %s object has been deleted, attribute access no longer allowed."
|
attrStr = "The C++ part of the %s object has been deleted, attribute access no longer allowed."
|
||||||
|
|
||||||
def __repr__( self ):
|
def __repr__(self):
|
||||||
if not hasattr(self, "_name"):
|
if not hasattr(self, "_name"):
|
||||||
self._name = "[unknown]"
|
self._name = "[unknown]"
|
||||||
return self.reprStr % self._name
|
return self.reprStr % self._name
|
||||||
|
|
||||||
def __getattr__( self, *args ):
|
def __getattr__(self, *args):
|
||||||
if not hasattr(self, "_name"):
|
if not hasattr(self, "_name"):
|
||||||
self._name = "[unknown]"
|
self._name = "[unknown]"
|
||||||
raise PyDeadObjectError( self.attrStr % self._name )
|
raise PyDeadObjectError(self.attrStr % self._name)
|
||||||
|
|
||||||
|
def __nonzero__(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PyUnbornObjectError(AttributeError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class _wxPyUnbornObject(object):
|
||||||
|
"""
|
||||||
|
Some stock objects are created when the wx.core module is
|
||||||
|
imported, but their C++ instance is not created until the wx.App
|
||||||
|
object is created and initialized. These object instances will
|
||||||
|
temporarily have their __class__ changed to this class so an
|
||||||
|
exception will be raised if they are used before the C++ instance
|
||||||
|
is ready.
|
||||||
|
"""
|
||||||
|
|
||||||
|
reprStr = "wxPython wrapper for UNBORN object! (The C++ object is not initialized yet.)"
|
||||||
|
attrStr = "The C++ part of this object has not been initialized, attribute access not allowed."
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
#if not hasattr(self, "_name"):
|
||||||
|
# self._name = "[unknown]"
|
||||||
|
return self.reprStr #% self._name
|
||||||
|
|
||||||
|
def __getattr__(self, *args):
|
||||||
|
#if not hasattr(self, "_name"):
|
||||||
|
# self._name = "[unknown]"
|
||||||
|
raise PyUnbornObjectError(self.attrStr) # % self._name )
|
||||||
|
|
||||||
def __nonzero__(self):
|
def __nonzero__(self):
|
||||||
return 0
|
return 0
|
||||||
@@ -186,5 +216,10 @@ from windows import *
|
|||||||
from controls import *
|
from controls import *
|
||||||
from misc import *
|
from misc import *
|
||||||
|
|
||||||
|
|
||||||
|
# Fixup the stock objects since they can't be used yet. (They will be
|
||||||
|
# restored in wx.PyApp.OnInit.)
|
||||||
|
_core._wxPyFixStockObjects()
|
||||||
|
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
|
@@ -26,6 +26,7 @@ RELEASE_VERSION
|
|||||||
SUBREL_VERSION
|
SUBREL_VERSION
|
||||||
VERSION
|
VERSION
|
||||||
RELEASE_NUMBER
|
RELEASE_NUMBER
|
||||||
|
PyUnbornObjectError
|
||||||
PyDeadObjectError
|
PyDeadObjectError
|
||||||
CallAfter
|
CallAfter
|
||||||
FutureCall
|
FutureCall
|
||||||
|
@@ -80,6 +80,11 @@ public:
|
|||||||
%newgroup
|
%newgroup
|
||||||
|
|
||||||
|
|
||||||
|
// %typemap(varout) wxFont* {
|
||||||
|
// // my typemap
|
||||||
|
// $result = SWIG_NewPointerObj((void *) $1, $1_descriptor, 0);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
// See also wxPy_ReinitStockObjects in helpers.cpp
|
// See also wxPy_ReinitStockObjects in helpers.cpp
|
||||||
%immutable;
|
%immutable;
|
||||||
|
@@ -28,9 +28,8 @@
|
|||||||
%include _core_api.i
|
%include _core_api.i
|
||||||
%include _core_rename.i
|
%include _core_rename.i
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%native(_wxPySetDictionary) __wxPySetDictionary;
|
%native(_wxPySetDictionary) __wxPySetDictionary;
|
||||||
|
%native(_wxPyFixStockObjects) __wxPyFixStockObjects;
|
||||||
|
|
||||||
%pythoncode {
|
%pythoncode {
|
||||||
%#// Give a reference to the dictionary of this module to the C++ extension
|
%#// Give a reference to the dictionary of this module to the C++ extension
|
||||||
|
@@ -359,7 +359,7 @@ void wxPyApp::_BootstrapApp()
|
|||||||
|
|
||||||
// The stock objects were all NULL when they were loaded into
|
// The stock objects were all NULL when they were loaded into
|
||||||
// SWIG generated proxies, so re-init those now...
|
// SWIG generated proxies, so re-init those now...
|
||||||
wxPy_ReinitStockObjects(False);
|
wxPy_ReinitStockObjects(3);
|
||||||
|
|
||||||
// It's now ok to generate exceptions for assertion errors.
|
// It's now ok to generate exceptions for assertion errors.
|
||||||
wxPythonApp->SetStartupComplete(True);
|
wxPythonApp->SetStartupComplete(True);
|
||||||
@@ -472,7 +472,7 @@ void __wxPyPreStart(PyObject* moduleDict)
|
|||||||
wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "wxPython");
|
wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "wxPython");
|
||||||
|
|
||||||
// Init the stock objects to a non-NULL value so SWIG doesn't create them as None
|
// Init the stock objects to a non-NULL value so SWIG doesn't create them as None
|
||||||
wxPy_ReinitStockObjects(True);
|
wxPy_ReinitStockObjects(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -564,33 +564,88 @@ bool wxPySwigInstance_Check(PyObject* obj) {
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// The stock objects are no longer created when the wxc module is imported, but
|
// The stock objects are no longer created when the wxc module is imported,
|
||||||
// only after the app object has been created. This function will be called before
|
// but only after the app object has been created. The
|
||||||
// OnInit is called so we can hack the new pointer values into the obj.this attributes.
|
// 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.
|
||||||
|
|
||||||
void wxPy_ReinitStockObjects(bool init)
|
|
||||||
|
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, dropwx(name));
|
||||||
|
wxCHECK_RET(obj != NULL, wxT("Unable to find stock object"));
|
||||||
|
wxCHECK_RET(wxPySwigInstance_Check(obj), wxT("Not a swig instance"));
|
||||||
|
|
||||||
|
// 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, 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, 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)
|
||||||
{
|
{
|
||||||
PyObject* obj;
|
PyObject* obj;
|
||||||
PyObject* ptrobj;
|
PyObject* ptrobj;
|
||||||
|
|
||||||
|
|
||||||
#define REINITOBJ(name, classname) \
|
#define REINITOBJ(name, classname) \
|
||||||
if ( init ) { name = (classname*)0xC0C0C0C0; } else { \
|
if (pass == 1) { name = (classname*)0xC0C0C0C0; } \
|
||||||
obj = PyDict_GetItemString(wxPython_dict, dropwx(#name)); \
|
else if (pass == 2) { rsoPass2(#name); } \
|
||||||
wxCHECK_RET(obj != NULL, wxT("Unable to find stock object for " #name)) \
|
else if (pass == 3) { rsoPass3(#name, #classname, (void*)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); }
|
|
||||||
|
|
||||||
#define REINITOBJ2(name, classname) \
|
#define REINITOBJ2(name, classname) \
|
||||||
if ( init ) { } else { \
|
if (pass == 1) { } \
|
||||||
obj = PyDict_GetItemString(wxPython_dict, dropwx(#name)); \
|
else if (pass == 2) { rsoPass2(#name); } \
|
||||||
wxCHECK_RET(obj != NULL, wxT("Unable to find stock object for " #name)) \
|
else if (pass == 3) { rsoPass3(#name, #classname, (void*)&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); }
|
|
||||||
|
|
||||||
|
|
||||||
REINITOBJ(wxNORMAL_FONT, wxFont);
|
REINITOBJ(wxNORMAL_FONT, wxFont);
|
||||||
|
Reference in New Issue
Block a user