summaryrefslogtreecommitdiffstats
path: root/libshiboken
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2011-08-24 21:58:56 -0300
committerMarcelo Lira <marcelo.lira@openbossa.org>2011-12-09 20:28:06 -0300
commit11a09fecdd6b6abf05884fbc931a9b6e8a43f9fb (patch)
treee35318b54abda283ffaae54b69f3cc2f0853a69f /libshiboken
parentcda2c514084ef0ac688e3770cc63c6449da892d5 (diff)
downloadshiboken-11a09fecdd6b6abf05884fbc931a9b6e8a43f9fb.tar.gz
shiboken-11a09fecdd6b6abf05884fbc931a9b6e8a43f9fb.tar.xz
shiboken-11a09fecdd6b6abf05884fbc931a9b6e8a43f9fb.zip
New conversions for containers.
Diffstat (limited to 'libshiboken')
-rw-r--r--libshiboken/sbkconverter.cpp122
-rw-r--r--libshiboken/sbkconverter.h22
-rw-r--r--libshiboken/tmp-referencetopython/sbkconverter.cpp196
-rw-r--r--libshiboken/tmp-referencetopython/sbkconverter.h174
4 files changed, 514 insertions, 0 deletions
diff --git a/libshiboken/sbkconverter.cpp b/libshiboken/sbkconverter.cpp
index 185fd2ad..3fd04db9 100644
--- a/libshiboken/sbkconverter.cpp
+++ b/libshiboken/sbkconverter.cpp
@@ -24,6 +24,7 @@
#include "sbkconverter_p.h"
#include "basewrapper_p.h"
#include "google/dense_hash_map"
+#include "autodecref.h"
#include "sbkdbg.h"
static SbkConverter** PrimitiveTypeConverters;
@@ -299,4 +300,125 @@ SbkConverter* primitiveTypeConverter(int index)
return PrimitiveTypeConverters[index];
}
+bool checkSequenceTypes(PyTypeObject* type, PyObject* pyIn)
+{
+ assert(type);
+ assert(pyIn);
+ if (!PySequence_Check(pyIn))
+ return false;
+ int size = PySequence_Size(pyIn);
+ for (int i = 0; i < size; ++i) {
+ if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, i)), type))
+ return false;
+ }
+ return true;
+}
+bool convertibleSequenceTypes(SbkConverter* converter, PyObject* pyIn)
+{
+ assert(converter);
+ assert(pyIn);
+ if (!PySequence_Check(pyIn))
+ return false;
+ int size = PySequence_Size(pyIn);
+ for (int i = 0; i < size; ++i) {
+ if (!isPythonToCppConvertible(converter, AutoDecRef(PySequence_GetItem(pyIn, i))))
+ return false;
+ }
+ return true;
+}
+bool convertibleSequenceTypes(SbkObjectType* type, PyObject* pyIn)
+{
+ assert(type);
+ return convertibleSequenceTypes(type->d->converter, pyIn);
+}
+
+bool checkPairTypes(PyTypeObject* firstType, PyTypeObject* secondType, PyObject* pyIn)
+{
+ assert(firstType);
+ assert(secondType);
+ assert(pyIn);
+ if (!PySequence_Check(pyIn))
+ return false;
+ if (PySequence_Size(pyIn) != 2)
+ return false;
+ if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, 0)), firstType))
+ return false;
+ if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, 1)), secondType))
+ return false;
+ return true;
+}
+bool convertiblePairTypes(SbkConverter* firstConverter, bool firstCheckExact, SbkConverter* secondConverter, bool secondCheckExact, PyObject* pyIn)
+{
+ assert(firstConverter);
+ assert(secondConverter);
+ assert(pyIn);
+ if (!PySequence_Check(pyIn))
+ return false;
+ if (PySequence_Size(pyIn) != 2)
+ return false;
+ AutoDecRef firstItem(PySequence_GetItem(pyIn, 0));
+ if (firstCheckExact) {
+ if (!PyObject_TypeCheck(firstItem, firstConverter->pythonType))
+ return false;
+ } else if (!isPythonToCppConvertible(firstConverter, firstItem)) {
+ return false;
+ }
+ AutoDecRef secondItem(PySequence_GetItem(pyIn, 1));
+ if (secondCheckExact) {
+ if (!PyObject_TypeCheck(secondItem, secondConverter->pythonType))
+ return false;
+ } else if (!isPythonToCppConvertible(secondConverter, secondItem)) {
+ return false;
+ }
+
+ return true;
+}
+
+bool checkDictTypes(PyTypeObject* keyType, PyTypeObject* valueType, PyObject* pyIn)
+{
+ assert(keyType);
+ assert(valueType);
+ assert(pyIn);
+ if (!PyDict_Check(pyIn))
+ return false;
+
+ PyObject* key;
+ PyObject* value;
+ Py_ssize_t pos = 0;
+ while (PyDict_Next(pyIn, &pos, &key, &value)) {
+ if (!PyObject_TypeCheck(key, keyType))
+ return false;
+ if (!PyObject_TypeCheck(value, valueType))
+ return false;
+ }
+ return true;
+}
+
+bool convertibleDictTypes(SbkConverter* keyConverter, bool keyCheckExact, SbkConverter* valueConverter, bool valueCheckExact, PyObject* pyIn)
+{
+ assert(keyConverter);
+ assert(valueConverter);
+ assert(pyIn);
+ if (!PyDict_Check(pyIn))
+ return false;
+ PyObject* key;
+ PyObject* value;
+ Py_ssize_t pos = 0;
+ while (PyDict_Next(pyIn, &pos, &key, &value)) {
+ if (keyCheckExact) {
+ if (!PyObject_TypeCheck(key, keyConverter->pythonType))
+ return false;
+ } else if (!isPythonToCppConvertible(keyConverter, key)) {
+ return false;
+ }
+ if (valueCheckExact) {
+ if (!PyObject_TypeCheck(value, valueConverter->pythonType))
+ return false;
+ } else if (!isPythonToCppConvertible(valueConverter, value)) {
+ return false;
+ }
+ }
+ return true;
+}
+
} } // namespace Shiboken::Conversions
diff --git a/libshiboken/sbkconverter.h b/libshiboken/sbkconverter.h
index 1fddf5a9..ba8dc8f2 100644
--- a/libshiboken/sbkconverter.h
+++ b/libshiboken/sbkconverter.h
@@ -221,6 +221,28 @@ LIBSHIBOKEN_API SbkConverter* getConverter(const char* typeName);
/// Returns the converter for a primitive type.
LIBSHIBOKEN_API SbkConverter* primitiveTypeConverter(int index);
+/// Returns true if a Python sequence is comprised of objects of the given \p type.
+LIBSHIBOKEN_API bool checkSequenceTypes(PyTypeObject* type, PyObject* pyIn);
+
+/// Returns true if a Python sequence is comprised of objects of a type convertible to the one represented by the given \p converter.
+LIBSHIBOKEN_API bool convertibleSequenceTypes(SbkConverter* converter, PyObject* pyIn);
+
+/// Returns true if a Python sequence is comprised of objects of a type convertible to \p type.
+LIBSHIBOKEN_API bool convertibleSequenceTypes(SbkObjectType* type, PyObject* pyIn);
+
+/// Returns true if a Python sequence can be converted to a C++ pair.
+LIBSHIBOKEN_API bool checkPairTypes(PyTypeObject* firstType, PyTypeObject* secondType, PyObject* pyIn);
+
+/// Returns true if a Python sequence can be converted to a C++ pair.
+LIBSHIBOKEN_API bool convertiblePairTypes(SbkConverter* firstConverter, bool firstCheckExact, SbkConverter* secondConverter, bool secondCheckExact, PyObject* pyIn);
+
+/// Returns true if a Python dictionary can be converted to a C++ hash or map.
+LIBSHIBOKEN_API bool checkDictTypes(PyTypeObject* keyType, PyTypeObject* valueType, PyObject* pyIn);
+
+/// Returns true if a Python dictionary can be converted to a C++ hash or map.
+LIBSHIBOKEN_API bool convertibleDictTypes(SbkConverter* keyConverter, bool keyCheckExact, SbkConverter* valueConverter, bool valueCheckExact, PyObject* pyIn);
+
+
#define SBK_PY_LONG_LONG_IDX 0
#define SBK_BOOL_IDX 1
#define SBK_CHAR_IDX 2
diff --git a/libshiboken/tmp-referencetopython/sbkconverter.cpp b/libshiboken/tmp-referencetopython/sbkconverter.cpp
new file mode 100644
index 00000000..61f04a18
--- /dev/null
+++ b/libshiboken/tmp-referencetopython/sbkconverter.cpp
@@ -0,0 +1,196 @@
+/*
+ * This file is part of the Shiboken Python Bindings Generator project.
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#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*)pyIn->ob_type;
+ 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
diff --git a/libshiboken/tmp-referencetopython/sbkconverter.h b/libshiboken/tmp-referencetopython/sbkconverter.h
new file mode 100644
index 00000000..edf67394
--- /dev/null
+++ b/libshiboken/tmp-referencetopython/sbkconverter.h
@@ -0,0 +1,174 @@
+/*
+ * This file is part of the Shiboken Python Bindings Generator project.
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: PySide team <contact@pyside.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SBK_CONVERTER_H
+#define SBK_CONVERTER_H
+
+#include <limits>
+#include <Python.h>
+#include "shibokenmacros.h"
+#include "basewrapper.h"
+
+extern "C"
+{
+
+/**
+ * SbkConverter is used to perform type conversions from C++
+ * to Python and vice-versa;.and it is also used for type checking.
+ * SbkConverter is a private structure that must be accessed
+ * using the functions provided by the converter API.
+ */
+struct SbkConverter;
+
+/**
+ * Given a void pointer to a C++ object, this function must return
+ * the proper Python object. It may be either an existing wrapper
+ * for the C++ object, or a newly create one. Or even the Python
+ * equivalent of the C++ value passed in the argument.
+ *
+ * C++ -> Python
+ */
+typedef PyObject* (*CppToPythonFunc)(const void*);
+
+/**
+ * This function converts a Python object to a C++ value, it may be
+ * a pointer, value, class, container or primitive type, passed via
+ * a void pointer, that will be cast properly inside the function.
+ * This function is usually returned by an IsConvertibleToCppFunc
+ * function, or obtained knowing the type of the Python object input,
+ * thus it will not check the Python object type, and will expect
+ * the void pointer to be pointing to a proper variable.
+ *
+ * Python -> C++
+ */
+typedef void (*PythonToCppFunc)(PyObject*,void*);
+
+/**
+ * Checks if the Python object passed in the argument is convertible to a
+ * C++ type defined inside the function, it returns the converter function
+ * that will transform a Python argument into a C++ value.
+ * It returns NULL if the Python object is not convertible to the C++ type
+ * that the function represents.
+ *
+ * Python -> C++ ?
+ */
+typedef PythonToCppFunc (*IsConvertibleToCppFunc)(PyObject*);
+
+} // extern "C"
+
+
+namespace Shiboken {
+namespace Conversions {
+
+/**
+ * Creates a converter for a wrapper type.
+ * \param type A Shiboken.ObjectType that will receive the new converter.
+ * \param toCppPointerConvFunc Function to retrieve the C++ pointer held by a Python wrapper.
+ * \param toCppPointerCheckFunc Check and return the retriever function of the C++ pointer held by a Python wrapper.
+ * \param pointerToPythonFunc Function to convert a C++ object to a Python \p type wrapper, keeping their identity.
+ * \param copyToPythonFunc Function to convert a C++ object to a Python \p type, copying the object.
+ * \returns The new converter referred by the wrapper \p type.
+ */
+LIBSHIBOKEN_API SbkConverter* createConverter(SbkObjectType* type,
+ PythonToCppFunc toCppPointerConvFunc,
+ IsConvertibleToCppFunc toCppPointerCheckFunc,
+ CppToPythonFunc pointerToPythonFunc,
+ CppToPythonFunc copyToPythonFunc = 0);
+
+LIBSHIBOKEN_API void deleteConverter(SbkConverter* converter);
+
+/**
+ * Adds a new conversion of a Python object to a C++ value.
+ * This is used in copy and implicit conversions.
+ */
+LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkConverter* converter,
+ PythonToCppFunc pythonToCppFunc,
+ IsConvertibleToCppFunc isConvertibleToCppFunc);
+LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkObjectType* type,
+ PythonToCppFunc pythonToCppFunc,
+ IsConvertibleToCppFunc isConvertibleToCppFunc);
+
+// C++ -> Python ---------------------------------------------------------------------------
+
+/**
+ * Retrieves the Python wrapper object for the given \p cppIn C++ pointer object.
+ * This function is used only for Value and Object Types.
+ * Example usage:
+ * TYPE* var;
+ * PyObject* pyVar = pointerToPython(SBKTYPE, &var);
+ */
+LIBSHIBOKEN_API PyObject* pointerToPython(SbkObjectType* type, const void* cppIn);
+
+/**
+ * Retrieves the Python wrapper object for the given C++ value pointed by \p cppIn.
+ * This function is used only for Value Types.
+ * Example usage:
+ * TYPE var;
+ * PyObject* pyVar = copyToPython(SBKTYPE, &var);
+ */
+LIBSHIBOKEN_API PyObject* copyToPython(SbkObjectType* type, const void* cppIn);
+
+// TODO:WRITEDOCSTRING - used only for Value Types - cppIn must point to a value
+/**
+ * Retrieves the Python wrapper object for the given C++ reference pointed by \p cppIn.
+ * This function is used only for Value and Object Types.
+ * It differs from pointerToPython() for not checking for a NULL pointer.
+ * Example usage:
+ * TYPE& var = SOMETHING;
+ * PyObject* pyVar = copyToPython(SBKTYPE, &var);
+ */
+LIBSHIBOKEN_API PyObject* referenceToPython(SbkObjectType* type, const void* cppIn);
+
+// TODO:WRITEDOCSTRING - used only for Primitives and Containers (and Value Types) - cppIn must point to a primitive, container or value type
+/// This is the same as copyToPython function.
+LIBSHIBOKEN_API PyObject* toPython(SbkConverter* converter, const void* cppIn);
+
+// Python -> C++ convertibility checks -----------------------------------------------------
+
+// TODO:WRITEDOCSTRING
+LIBSHIBOKEN_API PythonToCppFunc isPythonToCppPointerConvertible(SbkObjectType* type, PyObject* pyIn);
+
+// TODO:WRITEDOCSTRING- Returns a Python to C++ conversion function if true, or NULL if false.
+LIBSHIBOKEN_API PythonToCppFunc isPythonToCppValueConvertible(SbkObjectType* type, PyObject* pyIn);
+
+// TODO:WRITEDOCSTRING- Returns a Python to C++ conversion function if true, or NULL if false.
+LIBSHIBOKEN_API PythonToCppFunc isPythonToCppReferenceConvertible(SbkObjectType* type, PyObject* pyIn);
+
+/// This is the same as isPythonToCppValueConvertible function.
+LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(SbkConverter* converter, PyObject* pyIn);
+
+// Python -> C++ ---------------------------------------------------------------------------
+
+// TODO:WRITEDOCSTRING - function used by the generated [TYPE]_PythonToCpp_[TYPE]_PTR
+LIBSHIBOKEN_API void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, void* cppOut);
+
+// TODO:WRITEDOCSTRING - function used by the generated isConvertible when the PyObject is None,
+// making a C++ NULL pointer the result of the toCpp function call.
+// DRAFT: When the Python object is a Py_None, it's C++ conversion is always a NULL pointer.
+LIBSHIBOKEN_API void nonePythonToCppNullPtr(PyObject*, void* cppOut);
+
+// TODO:WRITEDOCSTRING - tells if \p toCpp is an implicit conversion.
+LIBSHIBOKEN_API bool isImplicitConversion(SbkObjectType* type, PythonToCppFunc toCpp);
+
+} } // namespace Shiboken::Conversions
+
+#endif // SBK_CONVERTER_H