diff options
author | Marcelo Lira <marcelo.lira@openbossa.org> | 2009-11-15 01:20:07 -0300 |
---|---|---|
committer | Marcelo Lira <marcelo.lira@openbossa.org> | 2009-11-18 09:22:50 -0300 |
commit | 1081714f5275261420a74ac333a117fd2bbca0c4 (patch) | |
tree | 6c0b17ba834516b10d0fe713ba9b80682ee4ee0d /libshiboken | |
parent | 80282277d0845a65739c33675aa9a91b10faa4b1 (diff) |
Shiboken retrieves a Python wrapper object from its corresponding
C++ object using the memory address of the former to retrieve the
latter. When multiple inheritance is involved, a C++ object passed
to C++ could be caught back downcasted to one of its parents with
a different memory address, following the memory layout for
multiple inheritance used by the compiler. This poses a problem
to keep the Python identity of a C++ object.
The solution was to extend the traditional PyTypeObject with a
number array with all the possible displacements to be added to
an object pointer to produce the memory addresses for the valid
pointers that could appear from all the possible type casts
involving the object parents. All the possible pointers are
registered (and unregistered) by the binding wrapper manager.
To store the multiple inheritance information the ShiboTypeObject
structure was created, expanding the original PyTypeObject with
two fields:
mi_offsets
an integer array containing the possible displacements from the
object base pointer. The array has the value -1 at its end.
mi_init
the function that will initialize the mi_offsets array it is
called at the first instaciation of a multiple inheriting object.
Diffstat (limited to 'libshiboken')
-rw-r--r-- | libshiboken/basewrapper.cpp | 21 | ||||
-rw-r--r-- | libshiboken/basewrapper.h | 18 | ||||
-rw-r--r-- | libshiboken/bindingmanager.cpp | 2 |
3 files changed, 30 insertions, 11 deletions
diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index d224e1ca9..04ab3a8f0 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -38,17 +38,26 @@ namespace Shiboken { PyObject* -PyBaseWrapper_New(PyTypeObject* instanceType, PyTypeObject* baseWrapperType, const void* cptr, uint hasOwnership) +PyBaseWrapper_New(PyTypeObject* instanceType, ShiboTypeObject* baseWrapperType, const void* cptr, uint hasOwnership) { if (!cptr) return 0; - PyObject *self = instanceType->tp_alloc(instanceType, 0); - ((Shiboken::PyBaseWrapper*)self)->baseWrapperType = baseWrapperType; - ((Shiboken::PyBaseWrapper*)self)->cptr = const_cast<void*>(cptr); - ((Shiboken::PyBaseWrapper*)self)->hasOwnership = hasOwnership; - ((Shiboken::PyBaseWrapper*)self)->validCppObject = 1; + PyObject* self = ((ShiboTypeObject*) instanceType)->pytype.tp_alloc((PyTypeObject*) instanceType, 0); + ((PyBaseWrapper*)self)->baseWrapperType = baseWrapperType; + ((PyBaseWrapper*)self)->cptr = const_cast<void*>(cptr); + ((PyBaseWrapper*)self)->hasOwnership = hasOwnership; + ((PyBaseWrapper*)self)->validCppObject = 1; + if (((ShiboTypeObject*) instanceType)->mi_init && !((ShiboTypeObject*) instanceType)->mi_offsets) + ((ShiboTypeObject*) instanceType)->mi_offsets = ((ShiboTypeObject*) instanceType)->mi_init(cptr); BindingManager::instance().assignWrapper(self, cptr); + if (((ShiboTypeObject*) instanceType)->mi_offsets) { + int* offset = ((ShiboTypeObject*) instanceType)->mi_offsets; + while (*offset != -1) { + BindingManager::instance().assignWrapper(self, (void*) ((size_t) cptr + (*offset))); + offset++; + } + } return self; } diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index a31e22638..e96e26569 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -44,10 +44,20 @@ namespace Shiboken extern "C" { +typedef int* (*MultipleInheritanceInitFunction)(const void*); + +// TODO: explain +struct ShiboTypeObject +{ + PyTypeObject pytype; + int* mi_offsets; + MultipleInheritanceInitFunction mi_init; +}; + struct PyBaseWrapper { PyObject_HEAD - PyTypeObject* baseWrapperType; + ShiboTypeObject* baseWrapperType; void* cptr; uint hasOwnership : 1; uint validCppObject : 1; @@ -55,8 +65,8 @@ struct PyBaseWrapper } // extern "C" -#define PyBaseWrapper_Check(op) PyObject_TypeCheck(op, &PyBaseWrapper_Type) -#define PyBaseWrapper_CheckExact(op) ((op)->ob_type == &PyBaseWrapper_Type) +#define PyBaseWrapper_Check(op) PyObject_TypeCheck(op, &Shiboken::PyBaseWrapper_Type) +#define PyBaseWrapper_CheckExact(op) ((op)->ob_type == &Shiboken::PyBaseWrapper_Type) #define PyBaseWrapper_cptr(pyobj) (((Shiboken::PyBaseWrapper*)pyobj)->cptr) #define PyBaseWrapper_setCptr(pyobj,c) (((Shiboken::PyBaseWrapper*)pyobj)->cptr = c) @@ -115,7 +125,7 @@ typedef struct { LIBSHIBOKEN_API PyAPI_FUNC(PyObject*) -PyBaseWrapper_New(PyTypeObject *instanceType, PyTypeObject *baseWrapperType, +PyBaseWrapper_New(PyTypeObject* instanceType, ShiboTypeObject* baseWrapperType, const void *cptr, uint hasOwnership = 1); inline bool diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 4ae49f868..ff1ac37e4 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -98,7 +98,7 @@ PyObject* BindingManager::getOverride(const void* cptr, const char* methodName) PyObject* wrapper = retrieveWrapper(cptr); if (wrapper) { - PyTypeObject* baseWrapperType = ((Shiboken::PyBaseWrapper*)wrapper)->baseWrapperType; + PyTypeObject* baseWrapperType = (PyTypeObject*) ((Shiboken::PyBaseWrapper*)wrapper)->baseWrapperType; PyObject* method = PyObject_GetAttrString(wrapper, const_cast<char*>(methodName)); if (method) { PyObject* defaultMethod = 0; |