/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt for Python. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "sbkconverter.h" #include "sbkconverter_p.h" #include "basewrapper_p.h" #include "sbkdbg.h" namespace Shiboken { namespace Conversions { static SbkConverter* createConverterObject(PyTypeObject* type, PythonToCppFunc toCppPointerConvFunc, IsConvertibleToCppFunc toCppPointerCheckFunc, CppToPythonFunc pointerToPythonFunc, CppToPythonFunc copyToPythonFunc) { SbkConverter* converter = new SbkConverter; converter->pythonType = type; converter->pointerToPython = pointerToPythonFunc; converter->copyToPython = copyToPythonFunc; converter->toCppPointerConversion = std::make_pair(toCppPointerCheckFunc, toCppPointerConvFunc); converter->toCppConversions.clear(); return converter; } SbkConverter* createConverter(SbkObjectType* type, PythonToCppFunc toCppPointerConvFunc, IsConvertibleToCppFunc toCppPointerCheckFunc, CppToPythonFunc pointerToPythonFunc, CppToPythonFunc copyToPythonFunc) { SbkConverter* converter = createConverterObject((PyTypeObject*)type, toCppPointerConvFunc, toCppPointerCheckFunc, pointerToPythonFunc, copyToPythonFunc); type->d->converter = converter; return converter; } void deleteConverter(SbkConverter* converter) { if (converter) { converter->toCppConversions.clear(); delete converter; } } void addPythonToCppValueConversion(SbkConverter* converter, PythonToCppFunc pythonToCppFunc, IsConvertibleToCppFunc isConvertibleToCppFunc) { converter->toCppConversions.push_back(std::make_pair(isConvertibleToCppFunc, pythonToCppFunc)); } void addPythonToCppValueConversion(SbkObjectType* type, PythonToCppFunc pythonToCppFunc, IsConvertibleToCppFunc isConvertibleToCppFunc) { addPythonToCppValueConversion(type->d->converter, pythonToCppFunc, isConvertibleToCppFunc); } PyObject* pointerToPython(SbkObjectType* type, const void* cppIn) { if (!cppIn) Py_RETURN_NONE; return type->d->converter->pointerToPython(cppIn); } static inline PyObject* CopyCppToPython(SbkConverter* converter, const void* cppIn) { assert(cppIn); return converter->copyToPython(cppIn); } PyObject* copyToPython(SbkObjectType* type, const void* cppIn) { return CopyCppToPython(type->d->converter, cppIn); } PyObject* toPython(SbkConverter* converter, const void* cppIn) { return CopyCppToPython(converter, cppIn); } PyObject* referenceToPython(SbkObjectType* type, const void* cppIn) { assert(cppIn); PyObject* pyOut = (PyObject*)BindingManager::instance().retrieveWrapper(cppIn); if (pyOut) { Py_INCREF(pyOut); return pyOut; } // If it is Value Type, return a copy of the C++ object. if (type->d->converter->copyToPython) return type->d->converter->copyToPython(cppIn); // If it is an Object Type, return a copy of the C++ object. return type->d->converter->pointerToPython(cppIn); } PythonToCppFunc isPythonToCppPointerConvertible(SbkObjectType* type, PyObject* pyIn) { assert(pyIn); return type->d->converter->toCppPointerConversion.first(pyIn); } static inline PythonToCppFunc IsPythonToCppConvertible(SbkConverter* converter, PyObject* pyIn) { assert(pyIn); ToCppConversionList& convs = converter->toCppConversions; for (ToCppConversionList::iterator conv = convs.begin(); conv != convs.end(); ++conv) { PythonToCppFunc toCppFunc = 0; if ((toCppFunc = (*conv).first(pyIn))) return toCppFunc; } return 0; } PythonToCppFunc isPythonToCppValueConvertible(SbkObjectType* type, PyObject* pyIn) { return IsPythonToCppConvertible(type->d->converter, pyIn); } PythonToCppFunc isPythonToCppConvertible(SbkConverter* converter, PyObject* pyIn) { return IsPythonToCppConvertible(converter, pyIn); } PythonToCppFunc isPythonToCppReferenceConvertible(SbkObjectType* type, PyObject* pyIn) { if (pyIn != Py_None) { PythonToCppFunc toCpp = isPythonToCppPointerConvertible(type, pyIn); if (toCpp) return toCpp; } return isPythonToCppValueConvertible(type, pyIn); } void nonePythonToCppNullPtr(PyObject*, void* cppOut) { assert(cppOut); *((void**)cppOut) = 0; } void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, void* cppOut) { assert(pyIn); assert(cppOut); SbkObjectType* inType = (SbkObjectType*)Py_TYPE(pyIn); if (ObjectType::hasCast(inType)) *((void**)cppOut) = ObjectType::cast(inType, (SbkObject*)pyIn, (PyTypeObject*)type); else *((void**)cppOut) = Object::cppPointer((SbkObject*)pyIn, (PyTypeObject*)type); } bool isImplicitConversion(SbkObjectType* type, PythonToCppFunc toCppFunc) { // This is the Object Type or Value Type conversion that only // retrieves the C++ pointer held in the Python wrapper. if (toCppFunc == type->d->converter->toCppPointerConversion.second) return false; // Object Types doesn't have any kind of value conversion, // only C++ pointer retrieval. if (type->d->converter->toCppConversions.empty()) return false; // The first conversion of the non-pointer conversion list is // a Value Type's copy to C++ function, which is not an implicit // conversion. // Otherwise it must be one of the implicit conversions. // Note that we don't check if the Python to C++ conversion is in // the list of the type's conversions, for it is expected that the // caller knows what he's doing. ToCppConversionList::iterator conv = type->d->converter->toCppConversions.begin(); return toCppFunc != (*conv).second; } } } // namespace Shiboken::Conversions