aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2009-11-25 16:52:48 -0300
committerMarcelo Lira <marcelo.lira@openbossa.org>2009-11-25 17:04:01 -0300
commitecc97184c0025d701ce7789e61ee55b84c29b942 (patch)
tree5ed9dea78fd8d024cb11798c83462c1edb5d5039
parentb973238682789a8f6dc68ec824df8c8e14be0ce9 (diff)
parent32ec53b32affed4707712f33cd6a370ecc62ad7f (diff)
Merged with multipleinheritance branch
-rw-r--r--cppgenerator.cpp113
-rw-r--r--cppgenerator.h14
-rw-r--r--headergenerator.cpp11
-rw-r--r--libshiboken/basewrapper.cpp22
-rw-r--r--libshiboken/basewrapper.h18
-rw-r--r--libshiboken/bindingmanager.cpp13
-rw-r--r--shibokengenerator.cpp46
-rw-r--r--shibokengenerator.h9
-rw-r--r--tests/libsample/multiple_derived.cpp37
-rw-r--r--tests/libsample/multiple_derived.h157
-rw-r--r--tests/samplebinding/CMakeLists.txt15
-rwxr-xr-xtests/samplebinding/multiple_derived_test.py161
-rw-r--r--tests/samplebinding/typesystem_sample.xml15
13 files changed, 493 insertions, 138 deletions
diff --git a/cppgenerator.cpp b/cppgenerator.cpp
index e07dd2ada..06051dbb4 100644
--- a/cppgenerator.cpp
+++ b/cppgenerator.cpp
@@ -89,6 +89,12 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
// headers
s << "// default includes" << endl;
s << "#include <shiboken.h>" << endl;
+
+ // The multiple inheritance initialization function
+ // needs the 'set' class from C++ STL.
+ if (hasMultipleInheritanceInAncestry(metaClass))
+ s << "#include <set>" << endl;
+
s << "#include \"" << moduleName().toLower() << "_python.h\"" << endl << endl;
QString converterImpl;
@@ -429,7 +435,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun
s << "* cptr;" << endl << endl;
if (rfunc->ownerClass()->isAbstract()) {
- s << INDENT << "if (type == &" << className << ") {" << endl;
+ s << INDENT << "if (type == (PyTypeObject*)&" << className << ") {" << endl;
{
Indentation indent(INDENT);
s << INDENT << "PyErr_SetString(PyExc_NotImplementedError," << endl;
@@ -440,7 +446,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun
s << INDENT << '}' << endl << endl;
}
- s << INDENT << "if (!PyType_IsSubtype(type, &" << className << "))" << endl;
+ s << INDENT << "if (!PyType_IsSubtype(type, (PyTypeObject*)&" << className << "))" << endl;
s << INDENT << INDENT << "return 0;" << endl << endl;
if (overloadData.maxArgs() > 0) {
@@ -1142,6 +1148,67 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
}
}
+QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClass* metaClass)
+{
+ QStringList result;
+ if (!metaClass->baseClassNames().isEmpty()) {
+ foreach (QString base, metaClass->baseClassNames()) {
+ result.append(QString("((size_t) static_cast<const %1*>(class_ptr)) - base").arg(base));
+ result.append(QString("((size_t) static_cast<const %1*>((%2*)((void*)class_ptr))) - base").arg(base).arg(metaClass->name()));
+ }
+ foreach (const AbstractMetaClass* pClass, getBaseClasses(metaClass))
+ result.append(getAncestorMultipleInheritance(pClass));
+ }
+ return result;
+}
+
+void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* metaClass)
+{
+ QString className = metaClass->qualifiedCppName();
+ QStringList ancestors = getAncestorMultipleInheritance(metaClass);
+ s << "static int mi_offsets[] = { ";
+ for (int i = 0; i < ancestors.size(); i++)
+ s << "-1, ";
+ s << "-1 };" << endl;
+ s << "int*" << endl;
+ s << multipleInheritanceInitializerFunctionName(metaClass) << "(const void* cptr)" << endl;
+ s << '{' << endl;
+ s << INDENT << "if (mi_offsets[0] == -1) {" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "std::set<int> offsets;" << endl;
+ s << INDENT << "std::set<int>::iterator it;" << endl;
+ s << INDENT << "const " << className << "* class_ptr = reinterpret_cast<const " << className << "*>(cptr);" << endl;
+ s << INDENT << "size_t base = (size_t) class_ptr;" << endl;
+
+ foreach (QString ancestor, ancestors)
+ s << INDENT << "offsets.insert(" << ancestor << ");" << endl;
+
+ s << endl;
+ s << INDENT << "offsets.erase(0);" << endl;
+ s << endl;
+
+ s << INDENT << "int i = 0;" << endl;
+ s << INDENT << "for (it = offsets.begin(); it != offsets.end(); it++) {" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "mi_offsets[i] = *it;" << endl;
+ s << INDENT << "i++;" << endl;
+ }
+ s << INDENT << '}' << endl;
+ }
+ s << INDENT << '}' << endl;
+ s << INDENT << "return mi_offsets;" << endl;
+ s << '}' << endl;
+}
+
+QString CppGenerator::multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass)
+{
+ if (!hasMultipleInheritanceInAncestry(metaClass))
+ return QString();
+ return QString("%1_mi_init").arg(cpythonBaseName(metaClass->typeEntry()));
+}
+
bool CppGenerator::supportsSequenceProtocol(const AbstractMetaClass* metaClass)
{
foreach(QString funcName, m_sequenceProtocol.keys()) {
@@ -1158,6 +1225,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
QString tp_dealloc;
QString tp_as_number('0');
QString tp_as_sequence('0');
+ QString mi_init('0');
QString cppClassName = metaClass->qualifiedCppName();
QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), "");
QString baseClassName;
@@ -1173,7 +1241,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
tp_as_sequence = QString("&Py%1_as_sequence").arg(cppClassName);
if (metaClass->baseClass())
- baseClassName = QString("&") + cpythonTypeName(metaClass->baseClass()->typeEntry());
+ baseClassName = QString("(PyTypeObject*)&%1").arg(cpythonTypeName(metaClass->baseClass()->typeEntry()));
else
baseClassName = QString("0");
@@ -1207,9 +1275,23 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
m_tpFuncs[func->name()] = cpythonFunctionName(func);
}
+ // class or some ancestor has multiple inheritance
+ const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass);
+ if (miClass) {
+ mi_init = QString("(Shiboken::MultipleInheritanceInitFunction)%1")
+ .arg(multipleInheritanceInitializerFunctionName(miClass));
+ if (metaClass == miClass) {
+ writeMultipleInheritanceInitializerFunction(s, metaClass);
+ } else {
+ s << "extern int* " << multipleInheritanceInitializerFunctionName(miClass);
+ s << "(const void* cptr);" << endl;
+ }
+ s << endl;
+ }
+
s << "// Class Definition -----------------------------------------------" << endl;
- s << "PyTypeObject " << className + "_Type" << " = {" << endl;
+ s << "Shiboken::ShiboTypeObject " << className + "_Type" << " = { {" << endl;
s << INDENT << "PyObject_HEAD_INIT(&PyType_Type)" << endl;
s << INDENT << "/*ob_size*/ 0," << endl;
s << INDENT << "/*tp_name*/ \"" << cppClassName << "\"," << endl;
@@ -1256,7 +1338,10 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
s << INDENT << "/*tp_cache*/ 0," << endl;
s << INDENT << "/*tp_subclasses*/ 0," << endl;
s << INDENT << "/*tp_weaklist*/ 0" << endl;
- s << "};" << endl << endl;
+ s << "}," << endl;
+ s << INDENT << "/*mi_offsets*/ 0," << endl;
+ s << INDENT << "/*mi_init*/ " << mi_init << endl;
+ s << "};" << endl;
}
@@ -1556,14 +1641,14 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu
if (cppEnum->enclosingClass()) {
addFunction = QString("PyDict_SetItemString(Py")
+ cppEnum->enclosingClass()->name()
- + "_Type.tp_dict,";
+ + "_Type.pytype.tp_dict,";
} else {
addFunction = "PyModule_AddObject(module,";
}
s << INDENT << "// init enum class: " << cppEnum->name() << endl;
- s << INDENT << "if (PyType_Ready(&" << cpythonName << "_Type) < 0)" << endl;
+ s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << cpythonName << "_Type) < 0)" << endl;
s << INDENT << INDENT << "return;" << endl;
s << INDENT << "Py_INCREF(&" << cpythonName << "_Type);" << endl;
@@ -1577,7 +1662,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu
QString flagsName = cpythonFlagsName(flags);
s << INDENT << "// init flags class: " << flags->name() << endl;
- s << INDENT << "if (PyType_Ready(&" << flagsName << "_Type) < 0)" << endl;
+ s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << flagsName << "_Type) < 0)" << endl;
s << INDENT << INDENT << "return;" << endl;
s << INDENT << "Py_INCREF(&" << flagsName << "_Type);" << endl;
@@ -1893,19 +1978,17 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m
// Multiple inheritance
if (metaClass->baseClassNames().size() > 1) {
- s << INDENT << pyTypeName << ".tp_bases = PyTuple_Pack(";
+ s << INDENT << pyTypeName << ".pytype.tp_bases = PyTuple_Pack(";
s << metaClass->baseClassNames().size();
s << ',' << endl;
QStringList bases;
- foreach (QString baseName, metaClass->baseClassNames()) {
- const AbstractMetaClass* base = classes().findClass(baseName);
- bases << QString("&%1").arg(cpythonTypeName(base->typeEntry()));
- }
+ foreach (const AbstractMetaClass* base, getBaseClasses(metaClass))
+ bases << QString("(PyTypeObject*)&%1").arg(cpythonTypeName(base->typeEntry()));
Indentation indent(INDENT);
s << INDENT << bases.join(", ") << ");" << endl << endl;
}
- s << INDENT << "if (PyType_Ready(&" << pyTypeName << ") < 0)" << endl;
+ s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << pyTypeName << ") < 0)" << endl;
s << INDENT << INDENT << "return;" << endl << endl;
s << INDENT << "Py_INCREF(&" << pyTypeName << ");" << endl;
s << INDENT << "PyModule_AddObject(module, \"" << metaClass->name() << "\"," << endl;
@@ -1950,7 +2033,7 @@ void CppGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* type)
s << '{' << endl;
s << INDENT << "return " << "Shiboken::";
if (type->isObject() || type->isValue()) {
- s << "PyBaseWrapper_New(&" << pyTypeName << ", &" << pyTypeName << ',';
+ s << "PyBaseWrapper_New((PyTypeObject*)&" << pyTypeName << ", &" << pyTypeName << ',';
} else {
// Type is enum or flag
s << "PyEnumObject_New(&" << pyTypeName << ", (long)";
diff --git a/cppgenerator.h b/cppgenerator.h
index 237dc68b7..a0e001f2f 100644
--- a/cppgenerator.h
+++ b/cppgenerator.h
@@ -127,6 +127,20 @@ private:
void writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum,
QString pyOpName, QString cppOpName, bool boolResult = false);
+ /// Writes the function that registers the multiple inheritance information for the classes that need it.
+ void writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* metaClass);
+
+ /**
+ * Returns the multiple inheritance initializer function for the given class.
+ * \param metaClass the class for whom the function name must be generated.
+ * \return name of the multiple inheritance information initializer function or
+ * an empty string if there is no multiple inheritance in its ancestry.
+ */
+ QString multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass);
+
+ /// Returns a list of all classes to which the given class could be casted.
+ QStringList getAncestorMultipleInheritance(const AbstractMetaClass* metaClass);
+
/// Returns true if the given class supports the python sequence protocol
bool supportsSequenceProtocol(const AbstractMetaClass* metaClass);
// Maps special function names to function parameters and return types
diff --git a/headergenerator.cpp b/headergenerator.cpp
index 9074726fd..a776e0c73 100644
--- a/headergenerator.cpp
+++ b/headergenerator.cpp
@@ -132,10 +132,15 @@ void HeaderGenerator::writeTypeCheckMacro(QTextStream& s, const TypeEntry* type)
{
QString pyTypeName = cpythonTypeName(type);
QString checkFunction = cpythonCheckFunction(type);
- s << "PyAPI_DATA(PyTypeObject) " << pyTypeName << ';' << endl;
- s << "#define " << checkFunction << "(op) PyObject_TypeCheck(op, &";
+ s << "PyAPI_DATA(";
+ if (type->isObject() || type->isValue())
+ s << "Shiboken::ShiboTypeObject";
+ else
+ s << "PyTypeObject";
+ s << ") " << pyTypeName << ';' << endl;
+ s << "#define " << checkFunction << "(op) PyObject_TypeCheck(op, (PyTypeObject*)&";
s << pyTypeName << ')' << endl;
- s << "#define " << checkFunction << "Exact(op) ((op)->ob_type == &";
+ s << "#define " << checkFunction << "Exact(op) ((op)->ob_type == (PyTypeObject*)&";
s << pyTypeName << ')' << endl;
}
diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp
index 1f58ae588..b0bb3d735 100644
--- a/libshiboken/basewrapper.cpp
+++ b/libshiboken/basewrapper.cpp
@@ -38,17 +38,27 @@ namespace Shiboken
{
PyObject*
-PyBaseWrapper_New(PyTypeObject* instanceType, PyTypeObject* baseWrapperType, const void* cptr, unsigned int hasOwnership)
+PyBaseWrapper_New(PyTypeObject* instanceType, ShiboTypeObject* baseWrapperType, const void* cptr, unsigned int 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) {
+ if (*offset > 0)
+ BindingManager::instance().assignWrapper(self, (void*) ((size_t) cptr + (*offset)));
+ offset++;
+ }
+ }
return self;
}
diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h
index 67f13c11d..a98b77e39 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;
unsigned int hasOwnership : 1;
unsigned int 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, unsigned int hasOwnership = 1);
inline bool
diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp
index a848e5e47..fc48348fc 100644
--- a/libshiboken/bindingmanager.cpp
+++ b/libshiboken/bindingmanager.cpp
@@ -85,7 +85,16 @@ void BindingManager::releaseWrapper(void *cptr)
void BindingManager::releaseWrapper(PyObject* wrapper)
{
- releaseWrapper(PyBaseWrapper_cptr(wrapper));
+ void* cptr = PyBaseWrapper_cptr(wrapper);
+ releaseWrapper(cptr);
+ if (((ShiboTypeObject*) wrapper->ob_type)->mi_offsets) {
+ int* offset = ((ShiboTypeObject*) wrapper->ob_type)->mi_offsets;
+ while (*offset != -1) {
+ if (*offset > 0)
+ BindingManager::instance().releaseWrapper((void*) ((size_t) cptr + (*offset)));
+ offset++;
+ }
+ }
}
PyObject* BindingManager::retrieveWrapper(const void* cptr)
@@ -101,7 +110,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;
diff --git a/shibokengenerator.cpp b/shibokengenerator.cpp
index f5d5b5046..5b6734cbf 100644
--- a/shibokengenerator.cpp
+++ b/shibokengenerator.cpp
@@ -850,8 +850,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s,
if (context) {
// replace template variable for the Python Type object for the
// class context in which the variable is used
- QString pytype = cpythonTypeName(context);
- code.replace("%PYTHONTYPEOBJECT", pytype);
+ code.replace("%PYTHONTYPEOBJECT", cpythonTypeName(context) + ".pytype");
}
if (func) {
@@ -919,7 +918,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s,
// replace template variable for the Python Type object for the
// class implementing the method in which the code snip is written
if (func->isStatic()) {
- code.replace("%PYTHONTYPEOBJECT", cpythonTypeName(func->implementingClass()));
+ code.replace("%PYTHONTYPEOBJECT", cpythonTypeName(func->implementingClass()) + ".pytype");
} else {
code.replace("%PYTHONTYPEOBJECT.", QString("%1->ob_type->").arg(pySelf));
code.replace("%PYTHONTYPEOBJECT", QString("%1->ob_type").arg(pySelf));
@@ -1078,30 +1077,31 @@ bool ShibokenGenerator::injectedCodeHasReturnValueAttribution(const AbstractMeta
return false;
}
-QStringList ShibokenGenerator::getBaseClasses(const AbstractMetaClass* metaClass)
+bool ShibokenGenerator::hasMultipleInheritanceInAncestry(const AbstractMetaClass* metaClass)
{
- QStringList baseClass;
-
- if (!metaClass->baseClassName().isEmpty() &&
- (metaClass->name() != metaClass->baseClassName()))
- baseClass.append(metaClass->baseClassName());
-
- foreach (AbstractMetaClass* interface, metaClass->interfaces()) {
- AbstractMetaClass* aux = interface->primaryInterfaceImplementor();
- if (!aux)
- continue;
-
- //skip templates
- if (!aux->templateArguments().isEmpty())
- continue;
-
- if (!aux->name().isEmpty() && (metaClass->name() != aux->name()))
- baseClass.append(aux->name());
- }
+ if (!metaClass || metaClass->baseClassNames().isEmpty())
+ return false;
+ if (metaClass->baseClassNames().size() > 1)
+ return true;
+ return hasMultipleInheritanceInAncestry(metaClass->baseClass());
+}
- return baseClass;
+AbstractMetaClassList ShibokenGenerator::getBaseClasses(const AbstractMetaClass* metaClass)
+{
+ AbstractMetaClassList baseClasses;
+ foreach (QString parent, metaClass->baseClassNames())
+ baseClasses << classes().findClass(parent);
+ return baseClasses;
}
+const AbstractMetaClass* ShibokenGenerator::getMultipleInheritingClass(const AbstractMetaClass* metaClass)
+{
+ if (!metaClass || metaClass->baseClassNames().isEmpty())
+ return 0;
+ if (metaClass->baseClassNames().size() > 1)
+ return metaClass;
+ return getMultipleInheritingClass(metaClass->baseClass());
+}
QString ShibokenGenerator::getApiExportMacro() const
{
diff --git a/shibokengenerator.h b/shibokengenerator.h
index 78a5498c2..af0b80a95 100644
--- a/shibokengenerator.h
+++ b/shibokengenerator.h
@@ -175,7 +175,14 @@ public:
int arg_count = -1) const;
bool hasInjectedCodeOrSignatureModification(const AbstractMetaFunction* func);
- QStringList getBaseClasses(const AbstractMetaClass* metaClass);
+
+ /// Returns true if there are cases of multiple inheritance in any of its ancestors.
+ bool hasMultipleInheritanceInAncestry(const AbstractMetaClass* metaClass);
+
+ /// Returns a list of parent classes for a method.
+ AbstractMetaClassList getBaseClasses(const AbstractMetaClass* metaClass);
+
+ const AbstractMetaClass* getMultipleInheritingClass(const AbstractMetaClass* metaClass);
void writeBaseConversion(QTextStream& s, const AbstractMetaType* type,
const AbstractMetaClass* context);
diff --git a/tests/libsample/multiple_derived.cpp b/tests/libsample/multiple_derived.cpp
index c6ce9f8a8..e8e4c4c3d 100644
--- a/tests/libsample/multiple_derived.cpp
+++ b/tests/libsample/multiple_derived.cpp
@@ -34,52 +34,37 @@
#include "multiple_derived.h"
-MDerived::MDerived()
+MDerived1::MDerived1() : m_value(100)
{
}
-MDerived::~MDerived()
+MDerived2::MDerived2() : m_value(200)
{
}
-const char*
-MDerived::name()
+MDerived3::MDerived3() : m_value(3000)
{
- return "MDerived";
}
-// Base2 methods
-const char*
-MDerived::funcName()
+MDerived4::MDerived4()
{
- return "MDerived.funcName";
}
-MBase1*
-MDerived::castToMBase1()
+MDerived5::MDerived5()
{
- MBase1* ptr = (MBase1*) this;
- return ptr;
-}
-
-MBase2*
-MDerived::castToMBase2()
-{
- MBase2* ptr = (MBase2*) this;
- return ptr;
}
-MDerived*
-MDerived::transformFromBase1(MBase1* self)
+MDerived1*
+MDerived1::transformFromBase1(Base1* self)
{
- MDerived* ptr = dynamic_cast<MDerived*>(self);
+ MDerived1* ptr = dynamic_cast<MDerived1*>(self);
return ptr;
}
-MDerived*
-MDerived::transformFromBase2(MBase2* self)
+MDerived1*
+MDerived1::transformFromBase2(Base2* self)
{
- MDerived* ptr = dynamic_cast<MDerived*>(self);
+ MDerived1* ptr = dynamic_cast<MDerived1*>(self);
return ptr;
}
diff --git a/tests/libsample/multiple_derived.h b/tests/libsample/multiple_derived.h
index 5ddfd112d..6fd35a5da 100644
--- a/tests/libsample/multiple_derived.h
+++ b/tests/libsample/multiple_derived.h
@@ -37,37 +37,160 @@
#include "libsamplemacros.h"
-class LIBSAMPLE_API MBase1
+class LIBSAMPLE_API Base1
{
public:
- ~MBase1() {}
- virtual const char* name() { return "MBase"; }
+ Base1() : m_value(1) {}
+ ~Base1() {}
+ virtual int base1Method() { return m_value; }
+private:
+ int m_value;
};
-class LIBSAMPLE_API MBase2
+class LIBSAMPLE_API Base2
{
public:
- ~MBase2() {}
- virtual const char* funcName() { return "MBase2.funcName"; }
+ Base2() : m_value(2) {}
+ ~Base2() {}
+ virtual int base2Method() { return m_value; }
+private:
+ int m_value;
};
-class LIBSAMPLE_API MDerived : public MBase1, public MBase2
+class LIBSAMPLE_API MDerived1 : public Base1, public Base2
{
public:
- MDerived();
- virtual ~MDerived();
+ MDerived1();
+ virtual ~MDerived1() {}
- // MBase1 methods
- const char* name();
+ virtual int mderived1Method() { return m_value; }
+ virtual int base1Method() { return Base1::base1Method() * 10; }
+ virtual int base2Method() { return Base2::base2Method() * 10; }
- // MBase2 methods
- const char* funcName();
+ Base1* castToBase1() { return (Base1*) this; }
+ Base2* castToBase2() { return (Base2*) this; }
- MBase1* castToMBase1();
- MBase2* castToMBase2();
+ static MDerived1* transformFromBase1(Base1 *self);
+ static MDerived1* transformFromBase2(Base2 *self);
- static MDerived* transformFromBase1(MBase1 *self);
- static MDerived* transformFromBase2(MBase2 *self);
+private:
+ int m_value;
};
+
+class SonOfMDerived1 : public MDerived1
+{
+public:
+ SonOfMDerived1() : m_value(0) {}
+ ~SonOfMDerived1() {}
+
+ MDerived1* castToMDerived1() { return (MDerived1*) this; }
+
+ int sonOfMDerived1Method() { return m_value; }
+private:
+ int m_value;
+};
+
+class Base3
+{
+public:
+ explicit Base3(int val = 3) : m_value(val) {}
+ ~Base3() {}
+ int base3Method() { return m_value; }
+private:
+ int m_value;
+};
+
+class Base4
+{
+public:
+ Base4() : m_value(4) {}
+ ~Base4() {}
+ int base4Method() { return m_value; }
+private:
+ int m_value;
+};
+
+class Base5
+{
+public:
+ Base5() : m_value(5) {}
+ ~Base5() {}
+ virtual int base5Method() { return m_value; }
+private:
+ int m_value;
+};
+
+class Base6
+{
+public:
+ Base6() : m_value(6) {}
+ ~Base6() {}
+ virtual int base6Method() { return m_value; }
+private:
+ int m_value;
+};
+
+
+class MDerived2 : public Base3, public Base4, public Base5, public Base6
+{
+public:
+ MDerived2();
+ virtual ~MDerived2() {}
+
+ int base4Method() { return Base3::base3Method() * 10; }
+ int mderived2Method() { return m_value; }
+
+ Base3* castToBase3() { return (Base3*) this; }
+ Base4* castToBase4() { return (Base4*) this; }
+ Base5* castToBase5() { return (Base5*) this; }
+ Base6* castToBase6() { return (Base6*) this; }
+
+private:
+ int m_value;
+};
+
+class MDerived3 : public MDerived1, public MDerived2
+{
+public:
+ MDerived3();
+ virtual ~MDerived3() {}
+
+ virtual int mderived3Method() { return m_value; }
+
+ MDerived1* castToMDerived1() { return (MDerived1*) this; }
+ MDerived2* castToMDerived2() { return (MDerived2*) this; }
+
+ Base3* castToBase3() { return (Base3*) this; }
+
+private:
+ int m_value;
+};
+
+class MDerived4 : public Base3, public Base4
+{
+public:
+ MDerived4();
+ ~MDerived4() {}
+
+ int mderived4Method() { return 0; }
+
+ Base3* castToBase3() { return (Base3*) this; }
+ Base4* castToBase4() { return (Base4*) this; }
+private:
+ int m_value;
+};
+
+class MDerived5 : public Base3, public Base4
+{
+public:
+ MDerived5();
+ ~MDerived5() {}
+
+ virtual int mderived5Method() { return 0; }
+
+ Base3* castToBase3() { return (Base3*) this; }
+ Base4* castToBase4() { return (Base4*) this; }
+};
+
#endif // MDERIVED_H
diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt
index 5f1f87348..7d37950e5 100644
--- a/tests/samplebinding/CMakeLists.txt
+++ b/tests/samplebinding/CMakeLists.txt
@@ -7,6 +7,12 @@ ${CMAKE_CURRENT_SOURCE_DIR}/typesystem_sample.xml
set(sample_SRC
${CMAKE_CURRENT_BINARY_DIR}/sample/abstractmodifications_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/abstract_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/base1_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/base2_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/base3_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/base4_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/base5_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/base6_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/collector_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/derived_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/echo_wrapper.cpp
@@ -20,9 +26,11 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/injectcode_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/kindergarten_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/listuser_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/mapuser_wrapper.cpp
-${CMAKE_CURRENT_BINARY_DIR}/sample/mbase1_wrapper.cpp
-${CMAKE_CURRENT_BINARY_DIR}/sample/mbase2_wrapper.cpp
-${CMAKE_CURRENT_BINARY_DIR}/sample/mderived_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/mderived1_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/mderived2_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/mderived3_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/mderived4_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/mderived5_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/modifications_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/nondefaultctor_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/objecttype_wrapper.cpp
@@ -40,6 +48,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/sample_module_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/samplenamespace_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/simplefile_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/size_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/sonofmderived1_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/str_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/time_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/virtualdtor_wrapper.cpp
diff --git a/tests/samplebinding/multiple_derived_test.py b/tests/samplebinding/multiple_derived_test.py
index 473cf8da0..56f1fe00d 100755
--- a/tests/samplebinding/multiple_derived_test.py
+++ b/tests/samplebinding/multiple_derived_test.py
@@ -29,55 +29,146 @@
import sys
import unittest
-from sample import MBase1, MBase2, MDerived
+from sample import Base1, Base2, Base3, Base4, Base5, Base6
+from sample import MDerived1, MDerived2, MDerived3, MDerived4, MDerived5, SonOfMDerived1
class MultipleDerivedTest(unittest.TestCase):
'''Test cases for multiple inheritance'''
def testIsInstance(self):
- '''MDerived is instance of its parents MBase1 and MBase2.'''
- a = MDerived()
- self.assert_(isinstance(a, MDerived))
- self.assert_(isinstance(a, MBase1))
- self.assert_(isinstance(a, MBase2))
+ '''MDerived1 is instance of its parents Base1 and Base2.'''
+ a = MDerived1()
+ self.assert_(isinstance(a, MDerived1))
+ self.assert_(isinstance(a, Base1))
+ self.assert_(isinstance(a, Base2))
def testIsSubclass(self):
- '''MDerived is subclass of its parents MBase1 and MBase2.'''
- self.assert_(issubclass(MDerived, MBase1))
- self.assert_(issubclass(MDerived, MBase2))
-
- def testCallToFunctionWithMBase1ArgumentThatCastsBackToMDerived(self):
- '''MDerived is passed as an MBase1 argument to method that returns it casted back to MDerived.'''
- a = MDerived()
- b = MDerived.transformFromBase1(a)
+ '''MDerived1 is subclass of its parents Base1 and Base2.'''
+ self.assert_(issubclass(MDerived1, Base1))
+ self.assert_(issubclass(MDerived1, Base2))
+
+ def testCallToFunctionWithBase1ArgumentThatCastsBackToMDerived1(self):
+ '''MDerived1 is passed as an Base1 argument to a method that returns it casted back to MDerived1.'''
+ a = MDerived1()
+ b = MDerived1.transformFromBase1(a)
self.assertEqual(a, b)
- def testCallToFunctionWithMBase2ArgumentThatCastsBackToMDerived(self):
- '''MDerived is passed as an MBase2 argument to method that returns it casted back to MDerived.'''
- a = MDerived()
- b = MDerived.transformFromBase2(a)
+ def testCallToFunctionWithBase2ArgumentThatCastsBackToMDerived1(self):
+ '''MDerived1 is passed as an Base2 argument to a method that returns it casted back to MDerived1.'''
+ a = MDerived1()
+ b = MDerived1.transformFromBase2(a)
self.assertEqual(a, b)
- def testCastFromMDerivedToMBase1(self):
- '''MDerived is casted by C++ to its first parent MBase2 and the binding must return the MDerived wrapper.'''
- a = MDerived()
+ def testCastFromMDerived1ToBases(self):
+ '''MDerived1 is casted by C++ to its parents and the binding must return the MDerived1 wrapper.'''
+ a = MDerived1()
refcnt = sys.getrefcount(a)
- b = a.castToMBase1()
- self.assert_(isinstance(b, MDerived))
- self.assertEqual(a, b)
- self.assertEqual(sys.getrefcount(a), refcnt + 1)
+ b1 = a.castToBase1()
+ b2 = a.castToBase2()
+ self.assert_(isinstance(b1, MDerived1))
+ self.assert_(isinstance(b2, MDerived1))
+ self.assertEqual(a, b1)
+ self.assertEqual(a, b2)
+ self.assertEqual(sys.getrefcount(a), refcnt + 2)
- """
- # This method must be commented since it will break the test flow until the problem is fixed.
- def testCastFromMDerivedToMBase2(self):
- '''MDerived is casted by C++ to its second parent MBase2 and the binding must return the MDerived wrapper.'''
- a = MDerived()
+ def testCastFromSonOfMDerived1ToBases(self):
+ '''SonOfMDerived1 is casted by C++ to its parents and the binding must return the SonOfMDerived1 wrapper.'''
+ a = SonOfMDerived1()
refcnt = sys.getrefcount(a)
- b = a.castToMBase2()
- self.assert_(isinstance(b, MDerived))
- self.assertEqual(a, b)
- self.assertEqual(sys.getrefcount(a), refcnt + 1)
- """
+ md1 = a.castToMDerived1()
+ b1 = a.castToBase1()
+ b2 = a.castToBase2()
+ self.assert_(isinstance(md1, SonOfMDerived1))
+ self.assert_(isinstance(b2, SonOfMDerived1))
+ self.assert_(isinstance(b2, SonOfMDerived1))
+ self.assertEqual(a, md1)
+ self.assertEqual(a, b1)
+ self.assertEqual(a, b2)
+ self.assertEqual(sys.getrefcount(a), refcnt + 3)
+
+ def testCastFromMDerived2ToBases(self):
+ '''MDerived2 is casted by C++ to its parents and the binding must return the MDerived2 wrapper.'''
+ a = MDerived2()
+ refcnt = sys.getrefcount(a)
+ b3 = a.castToBase3()
+ b4 = a.castToBase4()
+ b5 = a.castToBase5()
+ b6 = a.castToBase6()
+ self.assert_(isinstance(b3, MDerived2))
+ self.assert_(isinstance(b4, MDerived2))
+ self.assert_(isinstance(b5, MDerived2))
+ self.assert_(isinstance(b6, MDerived2))
+ self.assertEqual(a, b3)
+ self.assertEqual(a, b4)
+ self.assertEqual(a, b5)
+ self.assertEqual(a, b6)
+ self.assertEqual(sys.getrefcount(a), refcnt + 4)
+
+ def testCastFromMDerived3ToBases(self):
+ '''MDerived3 is casted by C++ to its parents and the binding must return the MDerived3 wrapper.'''
+ a = MDerived3()
+ refcnt = sys.getrefcount(a)
+ md1 = a.castToMDerived1()
+ md2 = a.castToMDerived2()
+ b1 = a.castToBase1()
+ b2 = a.castToBase2()
+ b3 = a.castToBase3()
+ b4 = a.castToBase4()
+ b5 = a.castToBase5()
+ b6 = a.castToBase6()
+ self.assert_(isinstance(md1, MDerived3))
+ self.assert_(isinstance(md2, MDerived3))
+ self.assert_(isinstance(b1, MDerived3))
+ self.assert_(isinstance(b2, MDerived3))
+ self.assert_(isinstance(b3, MDerived3))
+ self.assert_(isinstance(b4, MDerived3))
+ self.assert_(isinstance(b5, MDerived3))
+ self.assert_(isinstance(b6, MDerived3))
+ self.assertEqual(a, md1)
+ self.assertEqual(a, md2)
+ self.assertEqual(a, b1)
+ self.assertEqual(a, b2)
+ self.assertEqual(a, b3)
+ self.assertEqual(a, b4)
+ self.assertEqual(a, b5)
+ self.assertEqual(a, b6)
+ self.assertEqual(sys.getrefcount(a), refcnt + 8)
+
+ def testCastFromMDerived4ToBases(self):
+ '''MDerived4 is casted by C++ to its parents and the binding must return the MDerived4 wrapper.'''
+ a = MDerived4()
+ refcnt = sys.getrefcount(a)
+ b3 = a.castToBase3()
+ b4 = a.castToBase4()
+ self.assert_(isinstance(b3, MDerived4))
+ self.assert_(isinstance(b4, MDerived4))
+ self.assertEqual(a, b3)
+ self.assertEqual(a, b4)
+ self.assertEqual(sys.getrefcount(a), refcnt + 2)
+
+ def testCastFromMDerived5ToBases(self):
+ '''MDerived5 is casted by C++ to its parents and the binding must return the MDerived5 wrapper.'''
+ a = MDerived5()
+ refcnt = sys.getrefcount(a)
+ b3 = a.castToBase3()
+ b4 = a.castToBase4()
+ self.assert_(isinstance(b3, MDerived5))
+ self.assert_(isinstance(b4, MDerived5))
+ self.assertEqual(a, b3)
+ self.assertEqual(a, b4)
+ self.assertEqual(sys.getrefcount(a), refcnt + 2)
+
+ def testCastFromMDerived3ToBase3(self):
+ '''MDerived3 is casted by C++ to Base3 grandparent using both the inherited and reimplement castToBase3 methods.'''
+ a = MDerived3()
+ refcnt = sys.getrefcount(a)
+ b3_reimplemented = a.castToBase3()
+ b3_inherited = MDerived2.castToBase3(a)
+ self.assert_(isinstance(b3_reimplemented, MDerived3))
+ self.assert_(isinstance(b3_inherited, MDerived3))
+ self.assertEqual(a, b3_reimplemented)
+ self.assertEqual(a, b3_inherited)
+ self.assertEqual(sys.getrefcount(a), refcnt + 2)
if __name__ == '__main__':
unittest.main()
diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml
index b6ce70c5c..cfa87c23f 100644
--- a/tests/samplebinding/typesystem_sample.xml
+++ b/tests/samplebinding/typesystem_sample.xml
@@ -663,9 +663,18 @@
<object-type name="PrivateDtor" />
- <interface-type name="MBase1"/>
- <object-type name="MBase2"/>
- <object-type name="MDerived"/>
+ <object-type name="Base1"/>
+ <interface-type name="Base2"/>
+ <object-type name="Base3"/>
+ <interface-type name="Base4"/>
+ <interface-type name="Base5"/>
+ <interface-type name="Base6"/>
+ <object-type name="MDerived1"/>
+ <object-type name="MDerived2"/>
+ <object-type name="MDerived3"/>
+ <object-type name="MDerived4"/>
+ <object-type name="MDerived5"/>
+ <object-type name="SonOfMDerived1"/>
<value-type name="Echo">
<add-function signature="echo(const char *)" return-type="PyObject*">