summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--cppgenerator.cpp78
-rw-r--r--cppgenerator.h2
-rw-r--r--libshiboken/basewrapper.cpp39
-rw-r--r--libshiboken/basewrapper.h18
-rw-r--r--libshiboken/conversions.h2
-rw-r--r--tests/libother/number.h2
-rw-r--r--tests/libsample/abstract.h5
-rw-r--r--tests/libsample/derived.cpp8
-rw-r--r--tests/libsample/derived.h2
-rwxr-xr-xtests/samplebinding/typediscovery_test.py5
-rw-r--r--tests/samplebinding/typesystem_sample.xml3
12 files changed, 123 insertions, 42 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1253f923..600d21f2 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 1480d7d1..e8de1697 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 1df870d8..c9d24d24 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 358d6b24..a01fc57a 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 6383a768..2474fa59 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 48f28048..e40ebf2f 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 bbbd830b..d739802d 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 06f8d983..00857056 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 0a364625..39d9f30e 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 832148e3..c5acb948 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 14fd79e6..3c1bfdb9 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 c3522b84..77d10ef8 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">