aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cppgenerator.cpp74
-rw-r--r--cppgenerator.h2
-rw-r--r--libshiboken/basewrapper.cpp35
-rw-r--r--libshiboken/basewrapper.h18
-rw-r--r--libshiboken/conversions.h2
-rw-r--r--tests/libsample/abstract.h5
-rw-r--r--tests/libsample/derived.h1
-rw-r--r--tests/samplebinding/typesystem_sample.xml3
8 files changed, 104 insertions, 36 deletions
diff --git a/cppgenerator.cpp b/cppgenerator.cpp
index f4cc81a45..963d29f4a 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) {
@@ -1658,9 +1659,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)) {
@@ -1706,7 +1707,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$"), "");
@@ -1747,9 +1747,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
@@ -1841,7 +1838,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 << "};" << endl;
}
@@ -2593,6 +2590,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;
@@ -2643,11 +2663,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 2230d6ba2..728dbdc1e 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 fe9b73b1d..0deaefbe6 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,16 +226,12 @@ 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->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,
@@ -289,8 +281,6 @@ PyTypeObject SbkBaseWrapperType_Type = {
/*tp_weaklist*/ 0
};
-} // extern "C"
-
static PyObject* SbkBaseWrapper_get_dict(SbkBaseWrapper* obj)
{
if (!obj->ob_dict)
@@ -418,7 +408,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 ca876fccc..72b8d86f2 100644
--- a/libshiboken/basewrapper.h
+++ b/libshiboken/basewrapper.h
@@ -75,13 +75,22 @@ 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;
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
{
@@ -90,7 +99,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;
};
@@ -256,7 +265,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 5b559308e..3426f9439 100644
--- a/libshiboken/conversions.h
+++ b/libshiboken/conversions.h
@@ -160,7 +160,7 @@ struct ConverterBase<T*> : ConverterBase<T>
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/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.h b/tests/libsample/derived.h
index 5a4543155..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();
diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml
index 597bed610..40bb840ef 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">