aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cppgenerator.cpp26
-rw-r--r--cppgenerator.h2
-rw-r--r--headergenerator.cpp7
-rw-r--r--libshiboken/basewrapper.h9
-rw-r--r--libshiboken/conversions.h15
-rw-r--r--shibokengenerator.cpp5
-rw-r--r--shibokengenerator.h2
7 files changed, 64 insertions, 2 deletions
diff --git a/cppgenerator.cpp b/cppgenerator.cpp
index b35defab3..a4adea6ee 100644
--- a/cppgenerator.cpp
+++ b/cppgenerator.cpp
@@ -30,7 +30,6 @@
static Indentor INDENT;
-
CppGenerator::CppGenerator()
{
// sequence protocol functions
@@ -1256,6 +1255,25 @@ void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, c
s << '}' << endl;
}
+void CppGenerator::writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass)
+{
+ s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(PyObject* obj, ShiboTypeObject* desiredType)\n";
+ s << "{\n";
+ s << INDENT << metaClass->qualifiedCppName() << "* me = " << cpythonWrapperCPtr(metaClass, "obj") << ";\n";
+ AbstractMetaClassList bases = getBaseClasses(metaClass);
+ bool firstClass = true;
+ foreach(const AbstractMetaClass* baseClass, bases) {
+ s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == &" << cpythonTypeName(baseClass) << ")\n";
+ Indentation indent(INDENT);
+ s << INDENT << "return static_cast<" << baseClass->qualifiedCppName() << "*>(me);\n";
+ firstClass = false;
+ }
+ s << INDENT << "else\n";
+ Indentation indent(INDENT);
+ s << INDENT << "return me;\n";
+ s << "}\n\n";
+}
+
QString CppGenerator::multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass)
{
if (!hasMultipleInheritanceInAncestry(metaClass))
@@ -1280,6 +1298,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
QString tp_as_number('0');
QString tp_as_sequence('0');
QString mi_init('0');
+ QString mi_specialCast('0');
QString cppClassName = metaClass->qualifiedCppName();
QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), "");
QString baseClassName;
@@ -1340,6 +1359,8 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
s << "extern int* " << multipleInheritanceInitializerFunctionName(miClass);
s << "(const void* cptr);" << endl;
}
+ mi_specialCast = '&'+cpythonSpecialCastFunctionName(metaClass);
+ writeSpecialCastFunction(s, metaClass);
s << endl;
}
@@ -1394,7 +1415,8 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
s << INDENT << "/*tp_weaklist*/ 0" << endl;
s << "}," << endl;
s << INDENT << "/*mi_offsets*/ 0," << endl;
- s << INDENT << "/*mi_init*/ " << mi_init << endl;
+ s << INDENT << "/*mi_init*/ " << mi_init << ',' << endl;
+ s << INDENT << "/*mi_specialCast*/ " << mi_specialCast << endl;
s << "};" << endl;
}
diff --git a/cppgenerator.h b/cppgenerator.h
index b001acf4e..2dfeaa5f0 100644
--- a/cppgenerator.h
+++ b/cppgenerator.h
@@ -134,6 +134,8 @@ private:
/// Writes the function that registers the multiple inheritance information for the classes that need it.
void writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* metaClass);
+ /// Writes the implementation of special cast functions, used when we need to cast a class with mulltiple inheritance.
+ void writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass);
void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func);
/**
diff --git a/headergenerator.cpp b/headergenerator.cpp
index f0ef4ddfb..753e34554 100644
--- a/headergenerator.cpp
+++ b/headergenerator.cpp
@@ -195,6 +195,8 @@ void HeaderGenerator::finishGeneration()
QTextStream s_pts(&pythonTypeStuff);
QString convertersDecl;
QTextStream convDecl(&convertersDecl);
+ QString pyTypeFunctions;
+ QTextStream typeFunctions(&pyTypeFunctions);
Indentation indent(INDENT);
@@ -235,6 +237,9 @@ void HeaderGenerator::finishGeneration()
}
if (!metaClass->isNamespace()) {
+ // declaration/implementation of PyType function.
+ typeFunctions << "template<>\ninline ShiboTypeObject* PyType<" << metaClass->qualifiedCppName() << ">() { return &" << cpythonTypeName(metaClass) << "; }\n";
+
foreach (AbstractMetaClass* innerClass, metaClass->innerClasses()) {
if (shouldGenerate(innerClass)) {
s_cin << innerClass->typeEntry()->include().toString() << endl;
@@ -314,6 +319,8 @@ void HeaderGenerator::finishGeneration()
s << "namespace Shiboken" << endl << '{' << endl << endl;
+ s << "// PyType functions, to get the PyObjectType for a type T\n";
+ s << pyTypeFunctions << endl;
s << "// Generated converters declarations ----------------------------------" << endl << endl;
s << convertersDecl << endl;
diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h
index 56038c4ca..fd7825f1a 100644
--- a/libshiboken/basewrapper.h
+++ b/libshiboken/basewrapper.h
@@ -62,6 +62,13 @@ extern "C"
{
/// Function signature for the multiple inheritance information initializers that should be provided by classes with multiple inheritance.
typedef int* (*MultipleInheritanceInitFunction)(const void*);
+struct ShiboTypeObject;
+/**
+* Special cast function is used to correctly cast an object when it's
+* part of a multiple inheritance hierarchy.
+* The implementation of this function is auto generated by the generator and you don't need to care about it.
+*/
+typedef void* (*SpecialCastFunction)(PyObject*, ShiboTypeObject*);
/// PyTypeObject extended with C++ multiple inheritance information.
struct LIBSHIBOKEN_API ShiboTypeObject
@@ -69,6 +76,8 @@ struct LIBSHIBOKEN_API ShiboTypeObject
PyTypeObject pytype;
int* mi_offsets;
MultipleInheritanceInitFunction mi_init;
+ /// Special cast function, null if this class doesn't have multiple inheritance.
+ SpecialCastFunction mi_specialcast;
};
/// Base Python object for all the wrapped C++ classes.
diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h
index 4ec04f510..2b3c55162 100644
--- a/libshiboken/conversions.h
+++ b/libshiboken/conversions.h
@@ -65,6 +65,18 @@ struct ConverterBase
static T toCpp(PyObject* pyobj) { return *Converter<T*>::toCpp(pyobj); }
};
+/**
+* This function template is used to get the PyObjectType of a C++ type T.
+* It's main usage if handle multiple inheritance casts.
+* \see SpecialCastFunction
+*/
+template<typename T>
+inline ShiboTypeObject* PyType()
+{
+ assert(false); // This *SHOULD* never be called.
+ return 0;
+}
+
// Specialization meant to be used by abstract classes and object-types
// (i.e. classes with private copy constructors and = operators).
// Example: "struct Converter<AbstractClass* > : ConverterBase<AbstractClass* >"
@@ -86,6 +98,9 @@ struct ConverterBase<T*> : ConverterBase<T>
{
if (pyobj == Py_None)
return 0;
+ ShiboTypeObject* shiboType = reinterpret_cast<ShiboTypeObject*>(pyobj->ob_type);
+ if (shiboType->mi_specialcast)
+ return (T*) shiboType->mi_specialcast(pyobj, PyType<T>());
return (T*) ((Shiboken::PyBaseWrapper*) pyobj)->cptr;
}
};
diff --git a/shibokengenerator.cpp b/shibokengenerator.cpp
index 9f850c702..314909d08 100644
--- a/shibokengenerator.cpp
+++ b/shibokengenerator.cpp
@@ -240,6 +240,11 @@ QString ShibokenGenerator::cpythonFlagsName(const FlagsTypeEntry* flagsEntry)
return cpythonEnumFlagsName(moduleName(), flagsEntry->originalName());
}
+QString ShibokenGenerator::cpythonSpecialCastFunctionName(const AbstractMetaClass* metaClass)
+{
+ return cpythonBaseName(metaClass->typeEntry())+"SpecialCastFunction";
+}
+
QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass* metaClass, QString argName)
{
return cpythonWrapperCPtr(metaClass->typeEntry(), argName);
diff --git a/shibokengenerator.h b/shibokengenerator.h
index 968567e8f..beb88e4c6 100644
--- a/shibokengenerator.h
+++ b/shibokengenerator.h
@@ -249,6 +249,8 @@ public:
return QString();
return cpythonFlagsName(flags);
}
+ /// Returns the special cast function name, the function used to proper cast class with multiple inheritance.
+ QString cpythonSpecialCastFunctionName(const AbstractMetaClass* metaClass);
QString getFunctionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const;
QString getFormatUnitString(const AbstractMetaFunction* func) const;