diff options
author | Hugo Lima <hugo.lima@openbossa.org> | 2009-12-04 16:34:49 -0200 |
---|---|---|
committer | Marcelo Lira <marcelo.lira@openbossa.org> | 2009-12-05 02:36:16 -0300 |
commit | 7da644719810ab43d304101f21e0e514109ab86b (patch) | |
tree | fbeea3fa7bdde37cdda17e1141396da61850f711 | |
parent | c625d0acea417a7fa4beb9fa888fd2e67fd4e50c (diff) |
Multiple inheritance works as desired for 99.9% of all known use cases!
Reviewed by Marcelo Lira <marcelo.lira@openbossa.org>
-rw-r--r-- | cppgenerator.cpp | 26 | ||||
-rw-r--r-- | cppgenerator.h | 2 | ||||
-rw-r--r-- | headergenerator.cpp | 7 | ||||
-rw-r--r-- | libshiboken/basewrapper.h | 9 | ||||
-rw-r--r-- | libshiboken/conversions.h | 15 | ||||
-rw-r--r-- | shibokengenerator.cpp | 5 | ||||
-rw-r--r-- | shibokengenerator.h | 2 |
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; |