aboutsummaryrefslogtreecommitdiffstats
path: root/libshiboken
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2009-11-15 01:20:07 -0300
committerMarcelo Lira <marcelo.lira@openbossa.org>2009-11-18 09:22:50 -0300
commit1081714f5275261420a74ac333a117fd2bbca0c4 (patch)
tree6c0b17ba834516b10d0fe713ba9b80682ee4ee0d /libshiboken
parent80282277d0845a65739c33675aa9a91b10faa4b1 (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.cpp21
-rw-r--r--libshiboken/basewrapper.h18
-rw-r--r--libshiboken/bindingmanager.cpp2
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;