diff options
author | Marcelo Lira <marcelo.lira@openbossa.org> | 2010-03-04 16:34:45 -0300 |
---|---|---|
committer | Marcelo Lira <marcelo.lira@openbossa.org> | 2010-03-04 17:13:40 -0300 |
commit | f4db0c74e0f267c102fff6eb47ecc3eae628a637 (patch) | |
tree | e988b735d382f9d814078a9fba2009f9d6a38a39 | |
parent | dbeca960863dadbe8d496195bc60202619314214 (diff) | |
parent | edc9cbfcfde439ccfe7100f53efc5d1e4ec34480 (diff) |
Merge branch 'master' into extensibleconversions
Conflicts:
cppgenerator.cpp
libshiboken/basewrapper.cpp
Reviewed by Hugo Parente <hugo.lima@openbossa.org>
Reviewed by Lauro Moura <lauro.neto@openbossa.org>
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | cppgenerator.cpp | 78 | ||||
-rw-r--r-- | cppgenerator.h | 2 | ||||
-rw-r--r-- | libshiboken/basewrapper.cpp | 39 | ||||
-rw-r--r-- | libshiboken/basewrapper.h | 18 | ||||
-rw-r--r-- | libshiboken/conversions.h | 2 | ||||
-rw-r--r-- | tests/libother/number.h | 2 | ||||
-rw-r--r-- | tests/libsample/abstract.h | 5 | ||||
-rw-r--r-- | tests/libsample/derived.cpp | 8 | ||||
-rw-r--r-- | tests/libsample/derived.h | 2 | ||||
-rwxr-xr-x | tests/samplebinding/typediscovery_test.py | 5 | ||||
-rw-r--r-- | tests/samplebinding/typesystem_sample.xml | 3 |
12 files changed, 123 insertions, 42 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 1253f923e..600d21f2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} add_library(shiboken_generator SHARED ${shiboken_SRC}) target_link_libraries(shiboken_generator + ${APIEXTRACTOR_LIBRARY} ${GENERATORRUNNER_LIBRARY} ${QT_QTCORE_LIBRARY}) diff --git a/cppgenerator.cpp b/cppgenerator.cpp index 1480d7d1a..e8de16970 100644 --- a/cppgenerator.cpp +++ b/cppgenerator.cpp @@ -184,9 +184,6 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl s << endl; } - if (metaClass->isPolymorphic()) - writeTypeNameFunction(s, metaClass); - if (shouldGenerateCppWrapper(metaClass)) { s << "// Native ---------------------------------------------------------" << endl; s << endl; @@ -331,6 +328,10 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl writeClassDefinition(s, metaClass); s << endl; + if (metaClass->isPolymorphic()) + writeTypeDiscoveryFunction(s, metaClass); + + foreach (AbstractMetaEnum* cppEnum, metaClass->enums()) { bool hasFlags = cppEnum->typeEntry()->flags(); if (hasFlags) { @@ -1656,9 +1657,9 @@ void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, c void CppGenerator::writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass) { QString className = metaClass->qualifiedCppName(); - s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(PyObject* obj, SbkBaseWrapperType* desiredType)\n"; + s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(void* obj, SbkBaseWrapperType* desiredType)\n"; s << "{\n"; - s << INDENT << className << "* me = (" << className << "*) SbkBaseWrapper_cptr(obj);\n"; + s << INDENT << className << "* me = reinterpret_cast<" << className << "*>(obj);\n"; AbstractMetaClassList bases = getBaseClasses(metaClass); bool firstClass = true; foreach (const AbstractMetaClass* baseClass, getAllAncestors(metaClass)) { @@ -1754,7 +1755,6 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* QString tp_hash('0'); QString mi_init('0'); QString obj_copier('0'); - QString type_name_func('0'); QString mi_specialcast('0'); QString cppClassName = metaClass->qualifiedCppName(); QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), ""); @@ -1776,7 +1776,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* if (metaClass->isNamespace() || metaClass->hasPrivateDestructor()) { tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES"; tp_dealloc = metaClass->hasPrivateDestructor() ? - "(destructor)Shiboken::SbkBaseWrapper_Dealloc_PrivateDtor" : "0"; + "Shiboken::SbkBaseWrapper_Dealloc_PrivateDtor" : "0"; tp_init = "0"; } else { tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES";//|Py_TPFLAGS_HAVE_GC"; @@ -1786,7 +1786,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* deallocClassName = wrapperName(metaClass); else deallocClassName = cppClassName; - tp_dealloc = QString("(destructor)&(Shiboken::SbkBaseWrapper_Dealloc< %1 >)").arg(deallocClassName); + tp_dealloc = QString("&Shiboken::SbkBaseWrapper_Dealloc< %1 >").arg(deallocClassName); AbstractMetaFunctionList ctors = metaClass->queryFunctions(AbstractMetaClass::Constructors); tp_init = ctors.isEmpty() ? "0" : cpythonFunctionName(ctors.first()); @@ -1795,9 +1795,6 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* if (classNeedsGetattroFunction(metaClass)) tp_getattro = cpythonGetattroFunctionName(metaClass); - if (metaClass->isPolymorphic()) - type_name_func = cpythonBaseName(metaClass) + "_typeName"; - if (metaClass->hasPrivateDestructor()) tp_new = "0"; else @@ -1889,7 +1886,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* s << INDENT << "/*mi_offsets*/ 0," << endl; s << INDENT << "/*mi_init*/ " << mi_init << ',' << endl; s << INDENT << "/*mi_specialcast*/ " << mi_specialcast << ',' << endl; - s << INDENT << "/*type_name_func*/ " << type_name_func << ',' << endl; + s << INDENT << "/*type_discovery*/ 0," << endl; s << INDENT << "/*obj_copier*/ " << obj_copier << ',' << endl; s << INDENT << "/*ext_isconvertible*/ 0," << endl; s << INDENT << "/*ext_tocpp*/ 0" << endl; @@ -2643,6 +2640,29 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << "reinterpret_cast<SbkBaseWrapperType*>(" + cpythonTypeNameExt(miClass->typeEntry()) + ")->mi_init;" << endl << endl; } + // Set typediscovery struct or fill the struct of another one + if (metaClass->isPolymorphic()) { + s << INDENT << "// Fill type discovery information" << endl; + if (!metaClass->baseClass()) { + s << INDENT << cpythonTypeName(metaClass) << ".type_discovery = new Shiboken::TypeDiscovery;" << endl; + s << INDENT << cpythonTypeName(metaClass) << ".type_discovery->addTypeDiscoveryFunction(&"; + s << cpythonBaseName(metaClass) << "_typeDiscovery);" << endl; + } else { + // FIXME: What about mi classes? + AbstractMetaClass* baseClass = metaClass->baseClass(); + while (baseClass->baseClass()) + baseClass = baseClass->baseClass(); + s << INDENT << cpythonTypeName(metaClass) << ".type_discovery = " ; + s << "reinterpret_cast<SbkBaseWrapperType*>(" << cpythonTypeNameExt(baseClass->typeEntry()) << ")->type_discovery;" << endl; + + if (!metaClass->typeEntry()->polymorphicIdValue().isEmpty()) { + s << INDENT << cpythonTypeName(metaClass) << ".type_discovery->addTypeDiscoveryFunction(&"; + s << cpythonBaseName(metaClass) << "_typeDiscovery);" << endl; + } + } + s << endl; + } + s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << pyTypeName << ") < 0)" << endl; s << INDENT << INDENT << "return;" << endl << endl; @@ -2693,11 +2713,37 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << '}' << endl << endl; } -void CppGenerator::writeTypeNameFunction(QTextStream& s, const AbstractMetaClass* metaClass) +void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMetaClass* metaClass) { - Indentation indent(INDENT); - s << "static const char* " << cpythonBaseName(metaClass) << "_typeName(const void* cptr)\n{\n"; - s << INDENT << "return typeid(*reinterpret_cast<const " << metaClass->qualifiedCppName() << "*>(cptr)).name();\n"; + QString polymorphicExpr = metaClass->typeEntry()->polymorphicIdValue(); + bool shouldGenerateIt = !polymorphicExpr.isEmpty() || !metaClass->baseClass(); + if (!shouldGenerateIt) + return; + + s << "static SbkBaseWrapperType* " << cpythonBaseName(metaClass) << "_typeDiscovery(void* cptr, SbkBaseWrapperType* instanceType)\n{" << endl; + s << INDENT << "if (instanceType->mi_specialcast)" << endl; + { + Indentation indent(INDENT); + s << INDENT << "cptr = instanceType->mi_specialcast(cptr, &" << cpythonTypeName(metaClass) << ");" << endl; + } + + if (!metaClass->baseClass()) { + s << INDENT << "TypeResolver* typeResolver = TypeResolver::get(typeid(*reinterpret_cast<" + << metaClass->qualifiedCppName() << "*>(cptr)).name());" << endl; + s << INDENT << "if (typeResolver)" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return reinterpret_cast<SbkBaseWrapperType*>(typeResolver->pythonType());" << endl; + } + } else { + polymorphicExpr = polymorphicExpr.replace("%1", " reinterpret_cast<"+metaClass->qualifiedCppName()+"*>(cptr)"); + s << INDENT << " if (" << polymorphicExpr << ")" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return &" << cpythonTypeName(metaClass) << ';' << endl; + } + } + s << INDENT << "return 0;" << endl; s << "}\n\n"; } diff --git a/cppgenerator.h b/cppgenerator.h index 1df870d81..c9d24d246 100644 --- a/cppgenerator.h +++ b/cppgenerator.h @@ -68,7 +68,7 @@ private: void writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber = false, QString customType = ""); void writeTypeCheck(QTextStream& s, const OverloadData* overloadData, QString argumentName); - void writeTypeNameFunction(QTextStream& s, const AbstractMetaClass* metaClass); + void writeTypeDiscoveryFunction(QTextStream& s, const AbstractMetaClass* metaClass); void writeGetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass); diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 358d6b249..a01fc57af 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -125,12 +125,8 @@ PyObject* SbkBaseWrapper_New(SbkBaseWrapperType* instanceType, bool isExactType) { // Try to find the exact type of cptr. - if (!isExactType && instanceType->type_name_func) { - const char* typeName = instanceType->type_name_func(cptr); - TypeResolver* typeResolver = TypeResolver::get(typeName); - if (typeResolver) - instanceType = reinterpret_cast<SbkBaseWrapperType*>(typeResolver->pythonType()); - } + if (!isExactType && instanceType->type_discovery) + instanceType = instanceType->type_discovery->getType(cptr, instanceType); SbkBaseWrapper* self = reinterpret_cast<SbkBaseWrapper*>(SbkBaseWrapper_TpNew(reinterpret_cast<PyTypeObject*>(instanceType), 0, 0)); self->cptr = const_cast<void*>(cptr); @@ -230,18 +226,14 @@ SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) newType->mi_offsets = parentType->mi_offsets; newType->mi_init = parentType->mi_init; newType->mi_specialcast = parentType->mi_specialcast; - newType->type_name_func = parentType->type_name_func; newType->ext_isconvertible = parentType->ext_isconvertible; newType->ext_tocpp = parentType->ext_tocpp; + newType->type_discovery = parentType->type_discovery; + newType->obj_copier = parentType->obj_copier; return reinterpret_cast<PyObject*>(newType); } -extern "C" -{ - -struct SbkBaseWrapperType_Type; - PyTypeObject SbkBaseWrapperType_Type = { PyObject_HEAD_INIT(0) /*ob_size*/ 0, @@ -274,7 +266,7 @@ PyTypeObject SbkBaseWrapperType_Type = { /*tp_methods*/ 0, /*tp_members*/ 0, /*tp_getset*/ 0, - /*tp_base*/ 0, + /*tp_base*/ &PyType_Type, /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, @@ -291,8 +283,6 @@ PyTypeObject SbkBaseWrapperType_Type = { /*tp_weaklist*/ 0 }; -} // extern "C" - static PyObject* SbkBaseWrapper_get_dict(SbkBaseWrapper* obj) { if (!obj->ob_dict) @@ -374,8 +364,6 @@ void initShiboken() PyEval_InitThreads(); #endif - SbkBaseWrapperType_Type.tp_base = &PyType_Type; - if (PyType_Ready(&SbkBaseWrapperType_Type) < 0) Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapperType metatype."); @@ -422,7 +410,22 @@ void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const cha } -} // namespace Shiboken +SbkBaseWrapperType* TypeDiscovery::getType(const void* cptr, SbkBaseWrapperType* instanceType) const +{ + TypeDiscoveryFuncList::const_reverse_iterator it = m_discoveryFunctions.rbegin(); + for (; it != m_discoveryFunctions.rend(); ++it) { + SbkBaseWrapperType* type = (*it)(const_cast<void*>(cptr), instanceType); + if (type) + return type; + } + return instanceType; +} +void TypeDiscovery::addTypeDiscoveryFunction(Shiboken::TypeDiscoveryFunc func) +{ + m_discoveryFunctions.push_back(func); +} + +} // namespace Shiboken diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 6383a7686..2474fa591 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -75,9 +75,10 @@ struct SbkBaseWrapperType; * 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*, SbkBaseWrapperType*); -typedef const char* (*TypeNameFunction)(const void*); +typedef void* (*SpecialCastFunction)(void*, SbkBaseWrapperType*); typedef void* (*ObjectCopierFunction)(const void*); +typedef SbkBaseWrapperType* (*TypeDiscoveryFunc)(void*, SbkBaseWrapperType*); +typedef std::list<TypeDiscoveryFunc> TypeDiscoveryFuncList; typedef void* (*ExtendedToCppFunc)(PyObject*); typedef bool (*ExtendedIsConvertibleFunc)(PyObject*); @@ -85,6 +86,14 @@ typedef bool (*ExtendedIsConvertibleFunc)(PyObject*); LIBSHIBOKEN_API PyAPI_DATA(PyTypeObject) SbkBaseWrapperType_Type; LIBSHIBOKEN_API PyAPI_DATA(SbkBaseWrapperType) SbkBaseWrapper_Type; +class LIBSHIBOKEN_API TypeDiscovery { +public: + SbkBaseWrapperType* getType(const void* cptr, SbkBaseWrapperType* instanceType) const; + void addTypeDiscoveryFunction(TypeDiscoveryFunc func); +private: + TypeDiscoveryFuncList m_discoveryFunctions; +}; + /// PyTypeObject extended with C++ multiple inheritance information. struct LIBSHIBOKEN_API SbkBaseWrapperType { @@ -93,7 +102,7 @@ struct LIBSHIBOKEN_API SbkBaseWrapperType MultipleInheritanceInitFunction mi_init; /// Special cast function, null if this class doesn't have multiple inheritance. SpecialCastFunction mi_specialcast; - TypeNameFunction type_name_func; + TypeDiscovery* type_discovery; ObjectCopierFunction obj_copier; /// Extended "isConvertible" function to be used when a conversion operator is defined in another module. ExtendedIsConvertibleFunc ext_isconvertible; @@ -263,7 +272,8 @@ void SbkBaseWrapper_Dealloc(PyObject* self) if (SbkBaseWrapper_hasParentInfo(self)) destroyParentInfo(reinterpret_cast<SbkBaseWrapper*>(self)); SbkBaseWrapper_clearReferences(reinterpret_cast<SbkBaseWrapper*>(self)); - Py_TYPE(reinterpret_cast<SbkBaseWrapper*>(self))->tp_free(self); + + Py_TYPE(self)->tp_free(self); } LIBSHIBOKEN_API PyAPI_FUNC(void) SbkBaseWrapper_Dealloc_PrivateDtor(PyObject* self); diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 48f28048a..e40ebf2f0 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -252,7 +252,7 @@ struct ObjectTypeConverter return 0; SbkBaseWrapperType* shiboType = reinterpret_cast<SbkBaseWrapperType*>(pyobj->ob_type); if (shiboType->mi_specialcast) - return (T*) shiboType->mi_specialcast(pyobj, reinterpret_cast<SbkBaseWrapperType*>(SbkType<T>())); + return (T*) shiboType->mi_specialcast(SbkBaseWrapper_cptr(pyobj), reinterpret_cast<SbkBaseWrapperType*>(SbkType<T>())); return (T*) SbkBaseWrapper_cptr(pyobj); } }; diff --git a/tests/libother/number.h b/tests/libother/number.h index bbbd830ba..d739802d8 100644 --- a/tests/libother/number.h +++ b/tests/libother/number.h @@ -47,7 +47,7 @@ public: Str toStr() const; operator Str() const { return toStr(); } -protected: +private: int m_value; }; #endif // NUMBER_H diff --git a/tests/libsample/abstract.h b/tests/libsample/abstract.h index 06f8d983e..008570560 100644 --- a/tests/libsample/abstract.h +++ b/tests/libsample/abstract.h @@ -50,6 +50,10 @@ public: ClassNameAndId }; + enum Type { + TpAbstract, TpDerived + }; + int primitiveField; Point valueTypeField; ObjectType* objectTypeField; @@ -76,6 +80,7 @@ public: void callUnpureVirtual(); void show(PrintFormat format = Verbose); + virtual Type type() const { return TpAbstract; } protected: virtual const char* className() { return "Abstract"; } diff --git a/tests/libsample/derived.cpp b/tests/libsample/derived.cpp index 0a3646258..39d9f30e6 100644 --- a/tests/libsample/derived.cpp +++ b/tests/libsample/derived.cpp @@ -107,3 +107,11 @@ Abstract* Derived::triggerImpossibleTypeDiscovery() { return new SecrectClass; } + +struct AnotherSecretClass : public Derived { +}; + +Abstract* Derived::triggerAnotherImpossibleTypeDiscovery() +{ + return new AnotherSecretClass; +} diff --git a/tests/libsample/derived.h b/tests/libsample/derived.h index 832148e35..c5acb9488 100644 --- a/tests/libsample/derived.h +++ b/tests/libsample/derived.h @@ -64,6 +64,7 @@ public: virtual void unpureVirtual(); virtual PrintFormat returnAnEnum() { return Short; } + virtual Type type() const { return TpDerived; } // factory method static Abstract* createObject(); @@ -85,6 +86,7 @@ public: SomeInnerClass returnMyParameter(const SomeInnerClass& s) { return s; } static Abstract* triggerImpossibleTypeDiscovery(); + static Abstract* triggerAnotherImpossibleTypeDiscovery(); protected: const char* getClassName() { return className(); } virtual const char* className() { return "Derived"; } diff --git a/tests/samplebinding/typediscovery_test.py b/tests/samplebinding/typediscovery_test.py index 14fd79e6b..3c1bfdb98 100755 --- a/tests/samplebinding/typediscovery_test.py +++ b/tests/samplebinding/typediscovery_test.py @@ -34,9 +34,14 @@ class TypeDiscoveryTest(unittest.TestCase): def testPureVirtualsOfImpossibleTypeDiscovery(self): a = Derived.triggerImpossibleTypeDiscovery() + self.assertEqual(type(a), Abstract) # call some pure virtual method a.pureVirtual() + def testAnotherImpossibleTypeDiscovery(self): + a = Derived.triggerAnotherImpossibleTypeDiscovery() + self.assertEqual(type(a), Derived) + if __name__ == '__main__': unittest.main() diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index c3522b841..77d10ef8f 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -53,6 +53,7 @@ <enum-type name="Overload::FunctionEnum"/> <enum-type name="Overload::ParamEnum"/> <enum-type name="Event::EventType"/> + <enum-type name="Abstract::Type"/> <namespace-type name="SampleNamespace"/> @@ -60,7 +61,7 @@ <modify-function signature="id()" rename="id_"/> </object-type> - <object-type name="Derived"/> + <object-type name="Derived" polymorphic-id-expression="%1->type() == Derived::TpDerived" /> <value-type name="Derived::SomeInnerClass" /> <object-type name="ObjectType"> |