diff options
-rw-r--r-- | cppgenerator.cpp | 28 | ||||
-rw-r--r-- | headergenerator.cpp | 1 | ||||
-rw-r--r-- | libshiboken/conversions.h | 32 | ||||
-rw-r--r-- | shibokengenerator.cpp | 46 | ||||
-rw-r--r-- | shibokengenerator.h | 12 | ||||
-rwxr-xr-x | tests/samplebinding/reference_test.py | 2 |
6 files changed, 92 insertions, 29 deletions
diff --git a/cppgenerator.cpp b/cppgenerator.cpp index f032a6d6c..ebcf21a67 100644 --- a/cppgenerator.cpp +++ b/cppgenerator.cpp @@ -1183,11 +1183,11 @@ void CppGenerator::writeTypeCheck(QTextStream& s, const AbstractMetaType* argTyp if (!customType.isEmpty()) s << guessCPythonCheckFunction(customType); else if (argType->typeEntry()->isFlags()) - s << cpythonCheckFunction(((FlagsTypeEntry*) argType->typeEntry())->originator(), true); + s << cpythonIsConvertibleFunction(((FlagsTypeEntry*) argType->typeEntry())->originator(), true); else if (argType->isEnum()) - s << cpythonCheckFunction(argType, false, true); + s << cpythonIsConvertibleFunction(argType, false); else - s << cpythonCheckFunction(argType, isNumber); + s << cpythonIsConvertibleFunction(argType, isNumber); s << '(' << argumentName << ')'; } @@ -1240,6 +1240,7 @@ void CppGenerator::writeArgumentConversion(QTextStream& s, if (typeName.endsWith("&")) typeName.chop(1); } + typeName = typeName.trimmed(); bool hasImplicitConversions = !implicitConversions(argType).isEmpty(); @@ -1253,8 +1254,13 @@ void CppGenerator::writeArgumentConversion(QTextStream& s, s << argName << "_auto_ptr;" << endl; } - s << INDENT << typeName << ' ' << argName << " = "; - s << "Shiboken::Converter<" << typeName << " >::toCpp(" << pyArgName << ");" << endl; + if (usePySideExtensions() && typeName == "QStringRef") { + s << INDENT << "QString " << argName << "_qstring = Shiboken::Converter<QString>::toCpp(" << pyArgName << ");" << endl; + s << INDENT << "QStringRef " << argName << "(&" << argName << "_qstring);" << endl; + } else { + s << INDENT << typeName << ' ' << argName << " = "; + s << "Shiboken::Converter<" << typeName << " >::toCpp(" << pyArgName << ");" << endl; + } if (hasImplicitConversions) { s << INDENT << "if (!" << cpythonCheckFunction(argType->typeEntry()) << '(' << pyArgName << "))"; @@ -1437,8 +1443,8 @@ QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction* func, in ReportHandler::warning("Invalid Argument index on function modification: " + func->name()); } } else { - int real_index = OverloadData::numberOfRemovedArguments(func, argIndex - 1); - *wrappedClass = classes().findClass(func->arguments().at(real_index)->type()->typeEntry()->name()); + int realIndex = argIndex - 1 - OverloadData::numberOfRemovedArguments(func, argIndex - 1); + *wrappedClass = classes().findClass(func->arguments().at(realIndex)->type()->typeEntry()->name()); if ((argIndex == 1) && OverloadData::isSingleArgument(getFunctionGroups(func->implementingClass())[func->name()])) pyArgName = QString("arg"); @@ -1709,7 +1715,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f const AbstractMetaClass* wrappedClass = 0; QString pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass); if (!wrappedClass) { - s << "#error Invalid ownership modification for argument " << arg_mod.index << endl << endl; + s << "#error Invalid ownership modification for argument " << arg_mod.index << '(' << pyArgName << ')' << endl << endl; break; } @@ -1838,7 +1844,7 @@ void CppGenerator::writeExtendedIsConvertibleFunction(QTextStream& s, const Type isFirst = false; else s << endl << INDENT << " || "; - s << cpythonCheckFunction(metaClass->typeEntry()) << "(pyobj)"; + s << cpythonIsConvertibleFunction(metaClass->typeEntry()) << "(pyobj)"; } s << ';' << endl; s << '}' << endl; @@ -1856,7 +1862,7 @@ void CppGenerator::writeExtendedToCppFunction(QTextStream& s, const TypeEntry* e isFirst = false; else s << "else "; - s << "if (" << cpythonCheckFunction(metaClass->typeEntry()) << "(pyobj))" << endl; + s << "if (" << cpythonIsConvertibleFunction(metaClass->typeEntry()) << "(pyobj))" << endl; Indentation indent(INDENT); s << INDENT << "cptr = new " << externalType->name() << '('; writeToCppConversion(s, metaClass, "pyobj"); @@ -2322,7 +2328,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl s << INDENT; } - s << "if (" << cpythonCheckFunction(type, numberType) << "(other)) {" << endl; + s << "if (" << cpythonIsConvertibleFunction(type, numberType) << "(other)) {" << endl; { Indentation indent(INDENT); s << INDENT << "// " << func->signature() << endl; diff --git a/headergenerator.cpp b/headergenerator.cpp index d696b92cb..4543799e2 100644 --- a/headergenerator.cpp +++ b/headergenerator.cpp @@ -246,6 +246,7 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty s << INDENT << "static " << type->name() << " toCpp(PyObject* pyobj);" << endl; s << INDENT << "static bool isConvertible(PyObject* pyobj);" << endl; if (hasCustomConversion) { + s << INDENT << "static bool checkType(PyObject* pyobj);" << endl; s << INDENT << "static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<" << type->name() << (isAbstractOrObjectType ? "" : "*") << " >(cppObj)); }" << endl; s << INDENT << "static PyObject* toPython(const " << type->name() << "& cppObj);" << endl; diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 91243a07c..0d9c38608 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -131,6 +131,11 @@ template <typename T> struct Converter {}; template <typename T> struct Converter<T*> { + static inline bool checkType(PyObject* pyObj) + { + return Converter<T>::checkType(pyObj); + } + static inline bool isConvertible(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType<T>()); @@ -166,6 +171,7 @@ template <typename T> struct Converter<const T*> : Converter<T*> {}; template <typename T> struct Converter<T&> { + static inline bool checkType(PyObject* pyObj) { return Converter<T>::checkType(pyObj); } static inline bool isConvertible(PyObject* pyObj) { return Converter<T>::isConvertible(pyObj); } static inline PyObject* toPython(const T& cppobj) { return Converter<T*>::toPython(&cppobj); } static inline T& toCpp(PyObject* pyobj) { return *Converter<T*>::toCpp(pyobj); } @@ -177,6 +183,7 @@ template <typename T> struct Converter<const T&> : Converter<T&> {}; template<> struct Converter<void*> { + static inline bool checkType(PyObject* pyObj) { return false; } static inline bool isConvertible(PyObject* pyobj) { return true; } static PyObject* toPython(void* cppobj) { @@ -205,6 +212,8 @@ template <> struct Converter<const void*> : Converter<void*> {}; template <typename T> struct ValueTypeConverter { + static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); } + // The basic version of this method also tries to use the extended 'isConvertible' method. static inline bool isConvertible(PyObject* pyobj) { @@ -248,6 +257,7 @@ struct ValueTypeConverter template <typename T> struct ObjectTypeConverter { + static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); } /// Py_None objects are the only objects convertible to an object type (in the form of a NULL pointer). static inline bool isConvertible(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType<T>()); } /// Convenience overload that calls "toPython(const T*)" method. @@ -279,6 +289,7 @@ struct ObjectTypeConverter template <typename T> struct ObjectTypeReferenceConverter : ObjectTypeConverter<T> { + static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); } static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); } static inline PyObject* toPython(const T& cppobj) { return Converter<T*>::toPython(&cppobj); } static inline T& toCpp(PyObject* pyobj) @@ -301,6 +312,7 @@ template <> struct Converter<const PyObject*> : Converter<PyObject*> {}; template <> struct Converter<bool> { + static inline bool checkType(PyObject* pyobj) { return PyBool_Check(pyobj); } static inline bool isConvertible(PyObject* pyobj) { return PyInt_Check(pyobj); } static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<bool*>(cppobj)); } static inline PyObject* toPython(bool cppobj) { return PyBool_FromLong(cppobj); } @@ -361,6 +373,7 @@ struct OverFlowChecker<float, true> template <typename PyIntEquiv> struct Converter_PyInt { + static inline bool checkType(PyObject* pyobj) { return PyNumber_Check(pyobj); } static inline bool isConvertible(PyObject* pyobj) { return PyNumber_Check(pyobj); } static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<PyIntEquiv*>(cppobj)); } static inline PyObject* toPython(const PyIntEquiv& cppobj) { return PyInt_FromLong((long) cppobj); } @@ -396,6 +409,7 @@ struct Converter_PyULongInt : Converter_PyInt<T> template <typename CharType> struct CharConverter { + static inline bool checkType(PyObject* pyobj) { return SbkChar_Check(pyobj); } static inline bool isConvertible(PyObject* pyobj) { return SbkChar_Check(pyobj); } static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<CharType*>(cppobj)); } static inline PyObject* toPython(const CharType& cppobj) { return PyInt_FromLong(cppobj); } @@ -457,6 +471,7 @@ struct Converter<unsigned PY_LONG_LONG> template <typename PyFloatEquiv> struct Converter_PyFloat { + static inline bool checkType(PyObject* obj) { return PyNumber_Check(obj); } static inline bool isConvertible(PyObject* obj) { return PyNumber_Check(obj); } static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<PyFloatEquiv*>(cppobj)); } static inline PyObject* toPython(PyFloatEquiv cppobj) { return PyFloat_FromDouble((double) cppobj); } @@ -475,6 +490,7 @@ template <> struct Converter<double> : Converter_PyFloat<double> {}; template <typename CppEnum> struct EnumConverter { + static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<CppEnum>()); } static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<CppEnum>()); } static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<CppEnum*>(cppobj)); } static inline PyObject* toPython(CppEnum cppenum) @@ -491,6 +507,7 @@ struct EnumConverter template <typename CString> struct Converter_CString { + static inline bool checkType(PyObject* pyObj) { return PyString_Check(pyObj); } static inline bool isConvertible(PyObject* pyObj) { return pyObj == Py_None || PyString_Check(pyObj); } static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast<CString>(cppobj)); } static inline PyObject* toPython(CString cppobj) @@ -523,6 +540,11 @@ template <> struct Converter<const char*> : Converter_CString<const char*> {}; template <typename StdList> struct StdListConverter { + static inline bool checkType(PyObject* pyObj) + { + return isConvertible(pyObj); + } + static inline bool isConvertible(PyObject* pyObj) { if (PyObject_TypeCheck(pyObj, SbkType<StdList>())) @@ -567,6 +589,11 @@ struct StdListConverter template <typename StdPair> struct StdPairConverter { + static inline bool checkType(PyObject* pyObj) + { + return isConvertible(pyObj); + } + static inline bool isConvertible(PyObject* pyObj) { if (PyObject_TypeCheck(pyObj, SbkType<StdPair>())) @@ -606,6 +633,11 @@ struct StdPairConverter template <typename StdMap> struct StdMapConverter { + static inline bool checkType(PyObject* pyObj) + { + return isConvertible(pyObj); + } + static inline bool isConvertible(PyObject* pyObj) { if (PyObject_TypeCheck(pyObj, SbkType<StdMap>())) diff --git a/shibokengenerator.cpp b/shibokengenerator.cpp index 690490ce5..f2fd835c4 100644 --- a/shibokengenerator.cpp +++ b/shibokengenerator.cpp @@ -641,7 +641,7 @@ static QString checkFunctionName(QString baseName, bool genericNumberType, bool .arg((checkExact && !genericNumberType ? "Exact" : "")); } -QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType, bool genericNumberType, bool checkExact) +QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType, bool genericNumberType) { QString baseName = cpythonBaseName(metaType); if (metaType->typeEntry()->isCustom()) { @@ -653,7 +653,7 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType QTextStream s(&str); writeBaseConversion(s, metaType, 0); s.flush(); - return str + "isConvertible"; + return str + "checkType"; } } @@ -679,8 +679,27 @@ QString ShibokenGenerator::guessCPythonCheckFunction(const QString& type) return retval; } -QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry* type) +QString ShibokenGenerator::guessCPythonIsConvertible(const QString& type) { + QString retval; + AbstractMetaType* metaType = buildAbstractMetaTypeFromString(type); + if (metaType) { + retval = cpythonIsConvertibleFunction(metaType); + delete metaType; + } else if (type == "PyTypeObject") { + retval = "PyType_Check"; + } else { + retval = QString("%1_Check").arg(type); + } + return retval; +} + +QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry* type, bool genericNumberType, bool checkExact) +{ + if (checkExact) + return cpythonCheckFunction(type, genericNumberType, checkExact); + if (type->isCustom()) + return guessCPythonIsConvertible(type->name()); QString baseName; QTextStream s(&baseName); writeBaseConversion(s, type); @@ -689,18 +708,21 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry* type) return baseName; } -QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType* metaType) +QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType* metaType, bool genericNumberType) { - QString baseName; - QTextStream s(&baseName); - if (metaType->isValuePointer() || metaType->typeEntry()->isObject()) { - const AbstractMetaClass* context = classes().findClass(metaType->typeEntry()->name()); - writeBaseConversion(s, metaType, context); + + QString baseName = cpythonBaseName(metaType); + if (metaType->typeEntry()->isCustom()) { + return guessCPythonCheckFunction(metaType->typeEntry()->name()); + } else if (isNumber(baseName)) { + return genericNumberType ? "PyNumber_Check" : baseName+"_Check"; } else { - writeBaseConversion(s, metaType->typeEntry()); + QString str; + QTextStream s(&str); + writeBaseConversion(s, metaType, 0); + s.flush(); + return str + "isConvertible"; } - s << "isConvertible"; - s.flush(); return baseName; } diff --git a/shibokengenerator.h b/shibokengenerator.h index 786ace335..3985c95be 100644 --- a/shibokengenerator.h +++ b/shibokengenerator.h @@ -247,13 +247,15 @@ public: QString cpythonTypeName(const TypeEntry* type); QString cpythonTypeNameExt(const TypeEntry* type); QString cpythonCheckFunction(const TypeEntry* type, bool genericNumberType = false, bool checkExact = false); - QString cpythonCheckFunction(const AbstractMetaType* metaType, bool genericNumberType = false, bool checkExact = false); + QString cpythonCheckFunction(const AbstractMetaType* metaType, bool genericNumberType = false); QString guessCPythonCheckFunction(const QString& type); - QString cpythonIsConvertibleFunction(const TypeEntry* type); - QString cpythonIsConvertibleFunction(const AbstractMetaType* metaType); - QString cpythonIsConvertibleFunction(const AbstractMetaArgument* metaArg) { - return cpythonIsConvertibleFunction(metaArg->type()); + QString cpythonIsConvertibleFunction(const TypeEntry* type, bool genericNumberType = false, bool checkExact = false); + QString cpythonIsConvertibleFunction(const AbstractMetaType* metaType, bool genericNumberType = false); + QString cpythonIsConvertibleFunction(const AbstractMetaArgument* metaArg, bool genericNumberType = false) + { + return cpythonIsConvertibleFunction(metaArg->type(), genericNumberType); } + QString guessCPythonIsConvertible(const QString& type); QString cpythonFunctionName(const AbstractMetaFunction* func); QString cpythonMethodDefinitionName(const AbstractMetaFunction* func); QString cpythonGettersSettersDefinitionName(const AbstractMetaClass* metaClass); diff --git a/tests/samplebinding/reference_test.py b/tests/samplebinding/reference_test.py index f00e036e0..0c373ffac 100755 --- a/tests/samplebinding/reference_test.py +++ b/tests/samplebinding/reference_test.py @@ -64,7 +64,7 @@ class ReferenceTest(unittest.TestCase): def testCantSegFaultWhenReceiveNone(self): '''do not segfault when receiving None as argument.''' s = Str() - self.assertEqual(None, s) + self.assertNotEqual(None, s) def testMethodThatReceivesConstReference(self): '''Test a method that receives a const reference to an object as argument.''' |