diff options
-rw-r--r-- | cppgenerator.cpp | 13 | ||||
-rw-r--r-- | headergenerator.cpp | 39 | ||||
-rw-r--r-- | libshiboken/conversions.h | 61 | ||||
-rw-r--r-- | shibokengenerator.cpp | 78 | ||||
-rw-r--r-- | tests/samplebinding/complex_conversions.h | 4 | ||||
-rw-r--r-- | tests/samplebinding/list_conversions.h | 5 | ||||
-rw-r--r-- | tests/samplebinding/map_conversions.h | 5 | ||||
-rw-r--r-- | tests/samplebinding/oddbool_conversions.h | 5 | ||||
-rw-r--r-- | tests/samplebinding/pair_conversions.h | 4 |
9 files changed, 139 insertions, 75 deletions
diff --git a/cppgenerator.cpp b/cppgenerator.cpp index 4f4731e2b..64e603c2d 100644 --- a/cppgenerator.cpp +++ b/cppgenerator.cpp @@ -330,7 +330,9 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu && !m_formatUnits.contains(arg->type()->typeEntry()->name())); s << INDENT; if (convert) { - QString typeName = translateType(arg->type(), func->ownerClass()); + QString typeName = translateType(arg->type(), func->ownerClass(), ExcludeReference | ExcludeConst); + if (typeName.endsWith(" const")) + typeName = typeName.right(typeName.count()-5); if ((arg->type()->isQObject() || arg->type()->isObject()) && typeName.startsWith("const ")) typeName.remove(0, 6); @@ -1558,12 +1560,13 @@ void CppGenerator::writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEn Q_ASSERT(flagsEntry); QString cppName = cppEnum->typeEntry()->name(); QString cpythonName = cpythonEnumName(cppEnum); + QString checkFunction = cpythonCheckFunction(cppEnum->typeEntry()); s << "PyObject*" << endl; s << cpythonName << "___" << pyOpName << "__(PyObject* self, PyObject* arg)" << endl; s << '{' << endl; s << INDENT << "PyObject* py_result = 0;" << endl; - s << INDENT << "if (" << cpythonName << "_Check(arg)) {" << endl; + s << INDENT << "if (" << checkFunction << "(arg)) {" << endl; { Indentation indent(INDENT); s << INDENT << "py_result = Shiboken::Converter< "; @@ -1598,12 +1601,13 @@ void CppGenerator::writeFlagsInplaceOperator(QTextStream& s, const AbstractMetaE Q_ASSERT(flagsEntry); QString cppName = cppEnum->typeEntry()->name(); QString cpythonName = cpythonEnumName(cppEnum); + QString checkFunction = cpythonCheckFunction(cppEnum->typeEntry()); s << "PyObject*" << endl; s << cpythonName << "___" << pyOpName << "__(PyObject* self, PyObject* arg)" << endl; s << '{' << endl; s << INDENT << "PyObject* py_result = 0;" << endl; - s << INDENT << "if (" << cpythonName << "_Check(arg)) {" << endl; + s << INDENT << "if (" << checkFunction << "(arg)) {" << endl; { Indentation indent(INDENT); s << INDENT << "((" << flagsEntry->originalName() << ") ((PyEnumObject*)self)->ob_ival) " << cppOpName << endl; @@ -1637,12 +1641,13 @@ void CppGenerator::writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnu Q_ASSERT(flagsEntry); QString cppName = cppEnum->typeEntry()->name(); QString cpythonName = cpythonEnumName(cppEnum); + QString checkFunction = cpythonCheckFunction(cppEnum->typeEntry()); s << "PyObject*" << endl; s << cpythonName << "___" << pyOpName << "__(PyObject* self, PyObject* arg)" << endl; s << '{' << endl; s << INDENT << "PyObject* py_result = 0;" << endl; - s << INDENT << "if (" << cpythonName << "_Check(arg)) {" << endl; + s << INDENT << "if (" << checkFunction << "(arg)) {" << endl; { Indentation indent(INDENT); s << INDENT << "py_result = Shiboken::Converter< "; diff --git a/headergenerator.cpp b/headergenerator.cpp index 9ee63f749..fea228fd3 100644 --- a/headergenerator.cpp +++ b/headergenerator.cpp @@ -171,12 +171,7 @@ void HeaderGenerator::writeVirtualDispatcher(QTextStream& s, const AbstractMetaF void HeaderGenerator::writeTypeCheckMacro(QTextStream& s, const TypeEntry* type) { QString pyTypeName = cpythonTypeName(type); - QString checkFunction = cpythonCheckFunction(type); s << "PyAPI_DATA(PyTypeObject) " << pyTypeName << ';' << endl; - s << "#define " << checkFunction << "(op) PyObject_TypeCheck(op, &"; - s << pyTypeName << ')' << endl; - s << "#define " << checkFunction << "Exact(op) ((op)->ob_type == &"; - s << pyTypeName << ')' << endl; } void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* type) @@ -188,11 +183,9 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty s << "template<>" << endl; s << "struct Converter< " << cppName << " >" << endl << '{' << endl; - s << INDENT << "static PyObject* toPython("; - if (type->isObject()) - s << "const "; - s << cppName << " cppobj);" << endl; - s << INDENT << "static " << cppName << " toCpp(PyObject* pyobj);" << endl; + s << INDENT << "static bool isConvertible(const PyObject* pyObj);\n"; + s << INDENT << "static PyObject* toPython(const " << cppName << " cppobj);\n"; + s << INDENT << "static " << cppName << " toCpp(PyObject* pyobj);\n"; s << "};" << endl; } @@ -205,10 +198,14 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty if (type->isObject()) cppName.append('*'); - s << "inline PyObject* Converter< " << cppName << " >::toPython("; - if (type->isObject()) - s << "const "; - s << cppName << " cppobj)" << endl; + // write isConvertible function + s << "inline bool Converter<" << cppName << " >::isConvertible(const PyObject* pyObj)\n"; + s << "{\n"; + s << INDENT << "return PyObject_TypeCheck(pyObj, &" << pyTypeName << ");\n"; + s << "}\n"; + + // write toPython function + s << "inline PyObject* Converter<" << cppName << " >::toPython(const " << cppName << " cppobj)\n"; s << '{' << endl; s << INDENT << "PyObject* pyobj;" << endl; @@ -245,7 +242,8 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty s << INDENT << "return pyobj;" << endl; s << '}' << endl << endl; - s << "inline " << cppName << " Converter< " << cppName << " >::toCpp(PyObject* pyobj)" << endl; + // write toCpp function + s << "inline " << cppName << " Converter<" << cppName << " >::toCpp(PyObject* pyobj)" << endl; s << '{' << endl; if (type->isValue()) { @@ -269,8 +267,9 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty s << "if (" << cpythonCheckFunction(argType) << "(pyobj))" << endl; { Indentation indent(INDENT); - s << INDENT << "return " << cppName; - s << "(Converter< " << argType->cppSignature() << " >::toCpp(pyobj));" << endl; + s << INDENT << "return " << cppName << '('; + writeBaseConversion(s, argType, 0); + s << "toCpp(pyobj));\n"; } } } @@ -424,6 +423,9 @@ void HeaderGenerator::finishGeneration() s << "namespace Shiboken" << endl << '{' << endl << endl; + s << "// Generated converters declarations ----------------------------------" << endl << endl; + s << convertersDecl << endl; + s << "// User defined converters --------------------------------------------" << endl; foreach (TypeEntry* typeEntry, TypeDatabase::instance()->entries()) { if (typeEntry->hasConversionRule()) { @@ -432,8 +434,7 @@ void HeaderGenerator::finishGeneration() } } - s << "// Generated converters -----------------------------------------------" << endl << endl; - s << convertersDecl << endl; + s << "// Generated converters implementations -------------------------------" << endl << endl; s << convertersImpl << endl; s << "} // namespace Shiboken" << endl << endl; diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index ae6ab5e88..6c24780c1 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -45,20 +45,19 @@ namespace Shiboken template <typename T> struct Converter { - static PyObject* toPython(T cppobj); - static T toCpp(PyObject* pyobj); + static bool isConvertible(const PyObject* pyObj); + static PyObject* toPython(const T cppObj); + static T toCpp(PyObject* pyObj); }; -template <typename T> -struct Converter<T &> : Converter<T> {}; - -template <typename T> -struct Converter<const T &> : Converter<T> {}; - // Object Types --------------------------------------------------------------- template <> struct Converter<void*> { + static bool isConvertible(const PyObject* pyObj) + { + return pyObj != 0; + } static PyObject* toPython(void* cppobj) { PyObject* obj = BindingManager::instance().retrieveWrapper(cppobj); @@ -75,9 +74,13 @@ struct Converter<void*> template <> struct Converter<bool> { - static PyObject* toPython(bool holder) + static bool isConvertible(const PyObject* pyObj) + { + return PyBool_Check(pyObj); + } + static PyObject* toPython(const bool cppObj) { - return PyBool_FromLong(holder); + return PyBool_FromLong(cppObj); } static bool toCpp(PyObject* pyobj) { @@ -88,9 +91,13 @@ struct Converter<bool> template <typename PyIntEquiv> struct Converter_PyInt { - static PyObject* toPython(PyIntEquiv holder) + static bool isConvertible(const PyObject* pyObj) + { + return PyInt_Check(pyObj); + } + static PyObject* toPython(const PyIntEquiv cppObj) { - return PyInt_FromLong((long) holder); + return PyInt_FromLong((long) cppObj); } static PyIntEquiv toCpp(PyObject* pyobj) { @@ -111,7 +118,11 @@ template <> struct Converter<long> : Converter_PyInt<long> {}; template <> struct Converter<unsigned long> { - static PyObject* toPython(unsigned long holder) + static bool isConvertible(const PyObject* pyObj) + { + return PyLong_Check(pyObj); + } + static PyObject* toPython(const unsigned long holder) { return PyLong_FromUnsignedLong(holder); } @@ -124,7 +135,11 @@ struct Converter<unsigned long> template <> struct Converter<PY_LONG_LONG> { - static PyObject* toPython(PY_LONG_LONG holder) + static bool isConvertible(const PyObject* pyObj) + { + return PyLong_Check(pyObj); + } + static PyObject* toPython(const PY_LONG_LONG holder) { return PyLong_FromLongLong(holder); } @@ -137,7 +152,11 @@ struct Converter<PY_LONG_LONG> template <> struct Converter<unsigned PY_LONG_LONG> { - static PyObject* toPython(unsigned PY_LONG_LONG holder) + static bool isConvertible(const PyObject* pyObj) + { + return PyLong_Check(pyObj); + } + static PyObject* toPython(const unsigned PY_LONG_LONG holder) { return PyLong_FromUnsignedLongLong(holder); } @@ -150,7 +169,11 @@ struct Converter<unsigned PY_LONG_LONG> template <typename PyFloatEquiv> struct Converter_PyFloat { - static PyObject* toPython(PyFloatEquiv holder) + static bool isConvertible(const PyObject* pyObj) + { + return PyFloat_Check(pyObj); + } + static PyObject* toPython(const PyFloatEquiv holder) { return PyFloat_FromDouble((double) holder); } @@ -170,7 +193,11 @@ template <> struct Converter<double> : Converter_PyFloat<double> {}; template <typename CString> struct Converter_CString { - static PyObject* toPython(CString holder) + static bool isConvertible(const PyObject* pyObj) + { + return PyString_Check(pyObj); + } + static PyObject* toPython(const CString holder) { return PyString_FromString(holder); } diff --git a/shibokengenerator.cpp b/shibokengenerator.cpp index a25186de2..6f42bca72 100644 --- a/shibokengenerator.cpp +++ b/shibokengenerator.cpp @@ -59,30 +59,30 @@ void ShibokenGenerator::initPrimitiveTypesCorrespondences() m_pythonPrimitiveTypeName.clear(); // PyBool - m_pythonPrimitiveTypeName["bool"] = "PyBool"; + m_pythonPrimitiveTypeName["bool"] = "bool"; // PyInt - m_pythonPrimitiveTypeName["char"] = "PyInt"; - m_pythonPrimitiveTypeName["unsigned char"] = "PyInt"; - m_pythonPrimitiveTypeName["int"] = "PyInt"; - m_pythonPrimitiveTypeName["uint"] = "PyInt"; - m_pythonPrimitiveTypeName["unsigned int"] = "PyInt"; - m_pythonPrimitiveTypeName["short"] = "PyInt"; - m_pythonPrimitiveTypeName["ushort"] = "PyInt"; - m_pythonPrimitiveTypeName["unsigned short"] = "PyInt"; - m_pythonPrimitiveTypeName["long"] = "PyInt"; + m_pythonPrimitiveTypeName["char"] = "char"; + m_pythonPrimitiveTypeName["unsigned char"] = "unsigned char"; + m_pythonPrimitiveTypeName["int"] = "int"; + m_pythonPrimitiveTypeName["uint"] = "unsigned int"; + m_pythonPrimitiveTypeName["unsigned int"] = "unsigned int"; + m_pythonPrimitiveTypeName["short"] = "short"; + m_pythonPrimitiveTypeName["ushort"] = "unsigned short"; + m_pythonPrimitiveTypeName["unsigned short"] = "unsigned short"; + m_pythonPrimitiveTypeName["long"] = "long"; // PyFloat - m_pythonPrimitiveTypeName["double"] = "PyFloat"; - m_pythonPrimitiveTypeName["float"] = "PyFloat"; + m_pythonPrimitiveTypeName["double"] = "float"; + m_pythonPrimitiveTypeName["float"] = "double"; // PyLong - m_pythonPrimitiveTypeName["unsigned long"] = "PyLong"; - m_pythonPrimitiveTypeName["ulong"] = "PyLong"; - m_pythonPrimitiveTypeName["long long"] = "PyLong"; - m_pythonPrimitiveTypeName["__int64"] = "PyLong"; - m_pythonPrimitiveTypeName["unsigned long long"] = "PyLong"; - m_pythonPrimitiveTypeName["unsigned __int64"] = "PyLong"; + m_pythonPrimitiveTypeName["unsigned long"] = "unsigned long"; + m_pythonPrimitiveTypeName["ulong"] = "unsigned long"; + m_pythonPrimitiveTypeName["long long"] = "PY_LONG_LONG"; + m_pythonPrimitiveTypeName["__int64"] = "PY_LONG_LONG"; + m_pythonPrimitiveTypeName["unsigned long long"] = "PY_LONG_LONG"; + m_pythonPrimitiveTypeName["unsigned __int64"] = "unsigned PY_LONG_LONG"; // Python operators m_pythonOperators.clear(); @@ -261,15 +261,17 @@ QString ShibokenGenerator::writeBaseConversion(QTextStream& s, const AbstractMet typeName.remove(0, 6); QString conversion = typeName; - if (type->isValuePointer()) { - // If the type is a pointer to a Value Type, - // remove the pointer symbol ('*') + // If the type is a pointer to a Value Type, + // remove the pointer symbol ('*') + if (type->isValuePointer()) conversion.chop(1); - // And the constness, if any - if (conversion.startsWith("const ")) - conversion.remove(0, 6); - } - s << "Shiboken::Converter< " << conversion << " >::"; + + // And the constness, if any + if (conversion.startsWith("const ") && type->name() != "char") + conversion.remove(0, 6); + if (conversion.endsWith("&")) + conversion.chop(1); + s << "Shiboken::Converter<" << conversion << " >::"; return typeName; } @@ -489,21 +491,27 @@ bool ShibokenGenerator::isReverseOperator(const AbstractMetaFunction* func) args[1]->type()->typeEntry() == cppClass->typeEntry(); } -static QString checkFunctionName(QString baseName, bool genericNumberType) -{ - if (genericNumberType && ShibokenGenerator::isNumber(baseName)) - baseName = "PyNumber"; - return baseName + "_Check"; -} - QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* type, bool genericNumberType) { - return checkFunctionName(cpythonBaseName(type), genericNumberType); + if (genericNumberType && ShibokenGenerator::isNumber(cpythonBaseName(type))) + return "PyNumber_Check"; + + QString baseName; + QTextStream s(&baseName); + writeBaseConversion(s, type, 0); + s << "isConvertible"; + s.flush(); + return baseName; } QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry* type, bool genericNumberType) { - return checkFunctionName(cpythonBaseName(type), genericNumberType); + if (genericNumberType && ShibokenGenerator::isNumber(cpythonBaseName(type))) + return "PyNumber_Check"; + else { + QString typeName; + return "Converter<" + type->qualifiedCppName() + " >::isConvertible"; + } } QString ShibokenGenerator::argumentString(const AbstractMetaFunction *func, diff --git a/tests/samplebinding/complex_conversions.h b/tests/samplebinding/complex_conversions.h index 375c2f63e..bd1f2cd2a 100644 --- a/tests/samplebinding/complex_conversions.h +++ b/tests/samplebinding/complex_conversions.h @@ -1,6 +1,10 @@ template<> struct Converter<Complex> { + static bool isConvertible(const PyObject* pyObj) + { + return PyComplex_Check(pyObj); + } static PyObject* toPython(Complex cpx) { /* diff --git a/tests/samplebinding/list_conversions.h b/tests/samplebinding/list_conversions.h index 024f24b6e..97c7912c7 100644 --- a/tests/samplebinding/list_conversions.h +++ b/tests/samplebinding/list_conversions.h @@ -1,6 +1,11 @@ template <typename StdList> struct Converter_std_list { + static bool isConvertible(const PyObject* pyObj) + { + return PySequence_Check(const_cast<PyObject*>(pyObj)); + } + static PyObject* toPython(StdList holder) { PyObject* result = PyList_New((int) holder.size()); diff --git a/tests/samplebinding/map_conversions.h b/tests/samplebinding/map_conversions.h index a85aa909e..bd1b80f14 100644 --- a/tests/samplebinding/map_conversions.h +++ b/tests/samplebinding/map_conversions.h @@ -1,6 +1,11 @@ template <typename StdMap> struct Converter_std_map { + static bool isConvertible(const PyObject* pyObj) + { + return PyDict_Check(const_cast<PyObject*>(pyObj)); + } + static PyObject* toPython(StdMap holder) { PyObject* result = PyDict_New(); diff --git a/tests/samplebinding/oddbool_conversions.h b/tests/samplebinding/oddbool_conversions.h index 2e3f26414..7507cb52b 100644 --- a/tests/samplebinding/oddbool_conversions.h +++ b/tests/samplebinding/oddbool_conversions.h @@ -1,6 +1,11 @@ template <> struct Converter<OddBool> { + static bool isConvertible(const PyObject* pyObj) + { + return PyBool_Check(pyObj); + } + static PyObject* toPython(OddBool holder) { return PyBool_FromLong(holder.value()); diff --git a/tests/samplebinding/pair_conversions.h b/tests/samplebinding/pair_conversions.h index d5f1431ca..aae68d061 100644 --- a/tests/samplebinding/pair_conversions.h +++ b/tests/samplebinding/pair_conversions.h @@ -1,6 +1,10 @@ template <typename StdPair> struct Converter_std_pair { + static bool isConvertible(const PyObject* pyObj) + { + return PySequence_Check(const_cast<PyObject*>(pyObj)); + } static PyObject* toPython(StdPair holder) { typename StdPair::first_type first(holder.first); |