aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/libshiboken
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/libshiboken')
-rw-r--r--sources/shiboken2/libshiboken/CMakeLists.txt44
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp43
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.h22
-rw-r--r--sources/shiboken2/libshiboken/bindingmanager.cpp9
-rw-r--r--sources/shiboken2/libshiboken/sbkarrayconverter.cpp289
-rw-r--r--sources/shiboken2/libshiboken/sbkarrayconverter.h171
-rw-r--r--sources/shiboken2/libshiboken/sbkarrayconverter_p.h62
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter.cpp25
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter.h3
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter_p.h9
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.cpp13
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.h2
-rw-r--r--sources/shiboken2/libshiboken/sbkmodule.cpp19
-rw-r--r--sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp308
-rw-r--r--sources/shiboken2/libshiboken/shiboken.h1
15 files changed, 921 insertions, 99 deletions
diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt
index 6e725e6af..e87cf07fd 100644
--- a/sources/shiboken2/libshiboken/CMakeLists.txt
+++ b/sources/shiboken2/libshiboken/CMakeLists.txt
@@ -1,5 +1,22 @@
project(libshiboken)
+macro(get_numpy_location)
+ execute_process(
+ COMMAND ${PYTHON_EXECUTABLE} -c "if True:
+ import sys
+ import os
+ numpy = ''
+ for p in sys.path:
+ if 'site-' in p:
+ numpy = os.path.join(p, 'numpy')
+ if os.path.exists(numpy):
+ print(os.path.realpath(numpy))
+ break"
+ OUTPUT_VARIABLE PYTHON_NUMPY_LOCATION
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ message("PYTHON_NUMPY_LOCATION: " ${PYTHON_NUMPY_LOCATION})
+endmacro()
+
option(ENABLE_VERSION_SUFFIX "Used to use current version in suffix to generated files. This is used to allow multiples versions installed simultaneous." FALSE)
if(ENABLE_VERSION_SUFFIX)
set(shiboken2_SUFFIX "-${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}")
@@ -10,14 +27,6 @@ endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sbkversion.h.in"
"${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h" @ONLY)
-#Find installed sparsehash
-find_path(SPARSEHASH_INCLUDE_PATH sparseconfig.h PATH_SUFFIXES "/google/sparsehash")
-if(SPARSEHASH_INCLUDE_PATH)
- message(STATUS "Using system hash found in: ${SPARSEHASH_INCLUDE_PATH}")
-else()
- set(SPARSEHASH_INCLUDE_PATH ${CMAKE_SOURCE_DIR}/ext/sparsehash)
-endif()
-
set(libshiboken_MAJOR_VERSION ${shiboken_MAJOR_VERSION})
set(libshiboken_MINOR_VERSION ${shiboken_MINOR_VERSION})
set(libshiboken_MICRO_VERSION ${shiboken_MICRO_VERSION})
@@ -29,6 +38,7 @@ basewrapper.cpp
debugfreehook.cpp
gilstate.cpp
helper.cpp
+sbkarrayconverter.cpp
sbkconverter.cpp
sbkenum.cpp
sbkmodule.cpp
@@ -41,10 +51,19 @@ qapp_macro.cpp
voidptr.cpp
)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_BINARY_DIR}
- ${SBK_PYTHON_INCLUDE_DIR}
- ${SPARSEHASH_INCLUDE_PATH})
+get_numpy_location()
+
+set(libshiboken_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${SBK_PYTHON_INCLUDE_DIR})
+
+if (NOT "${PYTHON_NUMPY_LOCATION}" STREQUAL "")
+ set(libshiboken_INCLUDES ${libshiboken_INCLUDES} ${PYTHON_NUMPY_LOCATION}/core/include)
+ set(libshiboken_SRC ${libshiboken_SRC} sbknumpyarrayconverter.cpp)
+ add_definitions(-DHAVE_NUMPY -DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION)
+endif()
+
+set(APIEXTRACTOR_EXTRA_INCLUDES ${APIEXTRACTOR_EXTRA_INCLUDES} ${LIBXSLT_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
+
+include_directories(${libshiboken_INCLUDES})
add_library(libshiboken SHARED ${libshiboken_SRC})
target_link_libraries(libshiboken ${SBK_PYTHON_LIBRARIES})
set_target_properties(libshiboken PROPERTIES OUTPUT_NAME "shiboken2${shiboken2_SUFFIX}${PYTHON_SHARED_LIBRARY_SUFFIX}"
@@ -58,6 +77,7 @@ install(FILES
bindingmanager.h
gilstate.h
helper.h
+ sbkarrayconverter.h
sbkconverter.h
sbkenum.h
sbkmodule.h
diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp
index 270a5df94..d7d37971c 100644
--- a/sources/shiboken2/libshiboken/basewrapper.cpp
+++ b/sources/shiboken2/libshiboken/basewrapper.cpp
@@ -542,7 +542,6 @@ void DeallocVisitor::done()
DtorCallerVisitor::done();
}
-namespace Module { void init(); }
namespace Conversions { void init(); }
void init()
@@ -551,7 +550,6 @@ void init()
if (shibokenAlreadInitialised)
return;
- Module::init();
Conversions::init();
PyEval_InitThreads();
@@ -681,14 +679,6 @@ bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType)
return true;
}
-
-bool hasExternalCppConversions(SbkObjectType*) { return false; } // DEPRECATED.
-bool isExternalConvertible(SbkObjectType *, PyObject *) { return false; } // DEPRECATED.
-void setExternalCppConversionFunction(SbkObjectType*, ExtendedToCppFunc) {} // DEPRECATED.
-void setExternalIsConvertibleFunction(SbkObjectType*, ExtendedIsConvertibleFunc) {} // DEPRECATED.
-void* callExternalCppConversion(SbkObjectType*, PyObject*) { return 0; } // DEPRECATED.
-
-
bool hasCast(SbkObjectType* type)
{
return type->d->mi_specialcast != 0;
@@ -721,18 +711,6 @@ void setTypeDiscoveryFunctionV2(SbkObjectType* self, TypeDiscoveryFuncV2 func)
self->d->type_discovery = func;
}
-void setTypeDiscoveryFunction(SbkObjectType* self, TypeDiscoveryFunc func)
-{
- self->d->type_discovery = (TypeDiscoveryFuncV2)func;
-}
-
-TypeDiscoveryFunc getTypeDiscoveryFunction(SbkObjectType* self)
-{
- // This is an illegal cast because the return value is different,
- // but nobody ever used this function, so... =]
- return (TypeDiscoveryFunc)self->d->type_discovery;
-}
-
void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other)
{
self->d->mi_init = other->d->mi_init;
@@ -840,13 +818,15 @@ Py_hash_t hash(PyObject* pyObj)
static void setSequenceOwnership(PyObject* pyObj, bool owner)
{
if (PySequence_Check(pyObj)) {
- std::list<SbkObject*> objs = splitPyObject(pyObj);
- std::list<SbkObject*>::const_iterator it = objs.begin();
- for(; it != objs.end(); ++it) {
- if (owner)
- getOwnership(*it);
- else
- releaseOwnership(*it);
+ Py_ssize_t size = PySequence_Size(pyObj);
+ if (size > 0) {
+ std::list<SbkObject*> objs = splitPyObject(pyObj);
+ for (auto it = objs.begin(), end = objs.end(); it != end; ++it) {
+ if (owner)
+ getOwnership(*it);
+ else
+ releaseOwnership(*it);
+ }
}
} else if (Object::checkType(pyObj)) {
if (owner)
@@ -1053,11 +1033,6 @@ void makeValid(SbkObject* self)
}
}
-bool hasParentInfo(SbkObject* pyObj)
-{
- return pyObj->d->parentInfo != 0;
-}
-
void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType)
{
PyTypeObject* type = Py_TYPE(pyObj);
diff --git a/sources/shiboken2/libshiboken/basewrapper.h b/sources/shiboken2/libshiboken/basewrapper.h
index bd2d6820f..f6a7352f7 100644
--- a/sources/shiboken2/libshiboken/basewrapper.h
+++ b/sources/shiboken2/libshiboken/basewrapper.h
@@ -151,14 +151,6 @@ LIBSHIBOKEN_API bool isUserType(PyTypeObject* pyObj);
*/
LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType);
-
-LIBSHIBOKEN_API bool hasExternalCppConversions(SbkObjectType*); // DEPRECATED.
-LIBSHIBOKEN_API bool isExternalConvertible(SbkObjectType*, PyObject*); // DEPRECATED.
-LIBSHIBOKEN_API void setExternalCppConversionFunction(SbkObjectType*, ExtendedToCppFunc); // DEPRECATED.
-LIBSHIBOKEN_API void setExternalIsConvertibleFunction(SbkObjectType*, ExtendedIsConvertibleFunc); // DEPRECATED.
-LIBSHIBOKEN_API void* callExternalCppConversion(SbkObjectType*, PyObject*); // DEPRECATED.
-
-
/**
* Tells if the \p type represents an object of a class with multiple inheritance in C++.
* When this occurs, the C++ pointer held by the Python wrapper will need to be cast when
@@ -180,9 +172,6 @@ LIBSHIBOKEN_API void setOriginalName(SbkObjectType* self, const char* nam
LIBSHIBOKEN_API const char* getOriginalName(SbkObjectType* self);
LIBSHIBOKEN_API void setTypeDiscoveryFunctionV2(SbkObjectType* self, TypeDiscoveryFuncV2 func);
-LIBSHIBOKEN_API SBK_DEPRECATED(void setTypeDiscoveryFunction(SbkObjectType* self, TypeDiscoveryFunc func));
-LIBSHIBOKEN_API SBK_DEPRECATED(TypeDiscoveryFunc getTypeDiscoveryFunction(SbkObjectType* self));
-
LIBSHIBOKEN_API void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other);
LIBSHIBOKEN_API void setMultipleIheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction func);
LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* self);
@@ -333,11 +322,6 @@ LIBSHIBOKEN_API void releaseOwnership(PyObject* pyObj);
LIBSHIBOKEN_API void releaseOwnership(SbkObject* pyObj);
/**
- * Returns true if the pyObj holds information about their parents.
- */
-LIBSHIBOKEN_API bool hasParentInfo(SbkObject* pyObj);
-
-/**
* Get the C++ pointer of type \p desiredType from a Python object.
*/
LIBSHIBOKEN_API void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType);
@@ -387,12 +371,6 @@ LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child);
LIBSHIBOKEN_API void removeParent(SbkObject* child, bool giveOwnershipBack = true, bool keepReferenc = false);
/**
-* \internal This is an internal function called by tp_dealloc, it's exported just for technical reasons.
-* \note Do not call this function inside your bindings.
-*/
-LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true);
-
-/**
* Mark the object as invalid
*/
LIBSHIBOKEN_API void invalidate(SbkObject* self);
diff --git a/sources/shiboken2/libshiboken/bindingmanager.cpp b/sources/shiboken2/libshiboken/bindingmanager.cpp
index d7e122cd7..3308ef972 100644
--- a/sources/shiboken2/libshiboken/bindingmanager.cpp
+++ b/sources/shiboken2/libshiboken/bindingmanager.cpp
@@ -40,7 +40,6 @@
#include "basewrapper.h"
#include "basewrapper_p.h"
#include "bindingmanager.h"
-#include "google/dense_hash_map"
#include "sbkdbg.h"
#include "gilstate.h"
#include "sbkstring.h"
@@ -48,23 +47,23 @@
#include <cstddef>
#include <fstream>
+#include <unordered_map>
namespace Shiboken
{
-typedef google::dense_hash_map<const void*, SbkObject*> WrapperMap;
+typedef std::unordered_map<const void *, SbkObject *> WrapperMap;
class Graph
{
public:
typedef std::list<SbkObjectType*> NodeList;
- typedef google::dense_hash_map<SbkObjectType*, NodeList> Edges;
+ typedef std::unordered_map<SbkObjectType *, NodeList> Edges;
Edges m_edges;
Graph()
{
- m_edges.set_empty_key(0);
}
void addEdge(SbkObjectType* from, SbkObjectType* to)
@@ -172,8 +171,6 @@ void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject* wrapper, co
BindingManager::BindingManager()
{
m_d = new BindingManager::BindingManagerPrivate;
- m_d->wrapperMapper.set_empty_key((WrapperMap::key_type)0);
- m_d->wrapperMapper.set_deleted_key((WrapperMap::key_type)1);
#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK
debugInstallFreeHook();
diff --git a/sources/shiboken2/libshiboken/sbkarrayconverter.cpp b/sources/shiboken2/libshiboken/sbkarrayconverter.cpp
new file mode 100644
index 000000000..c22015709
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkarrayconverter.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 "sbkarrayconverter.h"
+#include "sbkarrayconverter_p.h"
+#include "helper.h"
+#include "sbkconverter.h"
+#include "sbkconverter_p.h"
+
+#include <longobject.h>
+#include <floatobject.h>
+
+#include <algorithm>
+
+static SbkArrayConverter *ArrayTypeConverters[Shiboken::Conversions::SBK_ARRAY_IDX_SIZE] [2] = {};
+
+namespace Shiboken {
+namespace Conversions {
+
+// Check whether Predicate is true for all elements of a sequence
+template <class Predicate>
+static bool sequenceAllOf(PyObject *pyIn, Predicate p)
+{
+ const Py_ssize_t size = PySequence_Size(pyIn);
+ for (Py_ssize_t i = 0; i < size; ++i) {
+ PyObject *item = PySequence_GetItem(pyIn, i);
+ const bool ok = p(item);
+ Py_XDECREF(item);
+ if (!ok)
+ return false;
+ }
+ return true;
+}
+
+// Convert a sequence to output iterator
+template <class T, class Converter>
+inline void convertPySequence(PyObject *pyIn, Converter c, T *out)
+{
+ const Py_ssize_t size = PySequence_Size(pyIn);
+ for (Py_ssize_t i = 0; i < size; ++i) {
+ PyObject *item = PySequence_GetItem(pyIn, i);
+ *out++ = c(item);
+ Py_XDECREF(item);
+ }
+}
+
+// Internal, for usage by numpy
+SbkArrayConverter *createArrayConverter(IsArrayConvertibleToCppFunc toCppCheckFunc)
+{
+ SbkArrayConverter *result = new SbkArrayConverter;
+ result->toCppConversions.push_back(toCppCheckFunc);
+ return result;
+}
+
+static PythonToCppFunc unimplementedArrayCheck(PyObject *, int, int)
+{
+ warning(PyExc_RuntimeWarning, 0, "SbkConverter: Unimplemented C++ array type.");
+ return nullptr;
+}
+
+SbkArrayConverter *unimplementedArrayConverter()
+{
+ static SbkArrayConverter *result = createArrayConverter(unimplementedArrayCheck);
+ return result;
+}
+
+// Integers
+
+static inline bool intCheck(PyObject *pyIn)
+{
+#ifdef IS_PY3K
+ return PyLong_Check(pyIn);
+#else
+ return PyInt_Check(pyIn);
+#endif
+}
+
+static short toShort(PyObject *pyIn) { return short(PyLong_AsLong(pyIn)); }
+
+static void sequenceToCppShortArray(PyObject *pyIn, void *cppOut)
+{
+ ArrayHandle<short> *handle = reinterpret_cast<ArrayHandle<short> *>(cppOut);
+ handle->allocate(PySequence_Size(pyIn));
+ convertPySequence(pyIn, toShort, handle->data());
+}
+
+static inline bool sequenceSizeCheck(PyObject *pyIn, int expectedSize = -1)
+{
+ if (expectedSize >= 0) {
+ const int size = int(PySequence_Size(pyIn));
+ if (size < expectedSize) {
+ warning(PyExc_RuntimeWarning, 0, "A sequence of size %d was passed to a function that expects %d.",
+ size, expectedSize);
+ return false;
+ }
+ }
+ return true;
+}
+
+static inline bool intArrayCheck(PyObject *pyIn, int expectedSize = -1)
+{
+ return PySequence_Check(pyIn) && sequenceAllOf(pyIn, intCheck)
+ && sequenceSizeCheck(pyIn, expectedSize);
+}
+
+static PythonToCppFunc sequenceToCppShortArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */)
+{
+ return intArrayCheck(pyIn, dim1) ? sequenceToCppShortArray : nullptr;
+}
+
+static short toUnsignedShort(PyObject *pyIn) { return static_cast<unsigned short>(PyLong_AsUnsignedLong(pyIn)); }
+
+static void sequenceToCppUnsignedShortArray(PyObject *pyIn, void *cppOut)
+{
+ ArrayHandle<unsigned short> *handle = reinterpret_cast<ArrayHandle<unsigned short> *>(cppOut);
+ handle->allocate(PySequence_Size(pyIn));
+ convertPySequence(pyIn, toUnsignedShort, handle->data());
+}
+
+static PythonToCppFunc sequenceToCppUnsignedShortArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */)
+{
+ return intArrayCheck(pyIn, dim1) ? sequenceToCppUnsignedShortArray : nullptr;
+}
+
+static void sequenceToCppIntArray(PyObject *pyIn, void *cppOut)
+{
+ ArrayHandle<int> *handle = reinterpret_cast<ArrayHandle<int> *>(cppOut);
+ handle->allocate(PySequence_Size(pyIn));
+ convertPySequence(pyIn, _PyLong_AsInt, handle->data());
+}
+
+static PythonToCppFunc sequenceToCppIntArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */)
+{
+ return intArrayCheck(pyIn, dim1) ? sequenceToCppIntArray : nullptr;
+}
+
+static void sequenceToCppUnsignedArray(PyObject *pyIn, void *cppOut)
+{
+ ArrayHandle<unsigned> *handle = reinterpret_cast<ArrayHandle<unsigned> *>(cppOut);
+ handle->allocate(PySequence_Size(pyIn));
+ convertPySequence(pyIn, PyLong_AsUnsignedLong, handle->data());
+}
+
+static PythonToCppFunc sequenceToCppUnsignedArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */)
+{
+ return intArrayCheck(pyIn, dim1) ? sequenceToCppUnsignedArray : nullptr;
+}
+
+static void sequenceToCppLongLongArray(PyObject *pyIn, void *cppOut)
+{
+ ArrayHandle<long long> *handle = reinterpret_cast<ArrayHandle<long long> *>(cppOut);
+ handle->allocate(PySequence_Size(pyIn));
+ convertPySequence(pyIn, PyLong_AsLongLong, handle->data());
+}
+
+static PythonToCppFunc sequenceToCppLongLongArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */)
+{
+ return intArrayCheck(pyIn, dim1) ? sequenceToCppLongLongArray : nullptr;
+}
+
+static void sequenceToCppUnsignedLongLongArray(PyObject *pyIn, void *cppOut)
+{
+ ArrayHandle<unsigned long long> *handle = reinterpret_cast<ArrayHandle<unsigned long long> *>(cppOut);
+ handle->allocate(PySequence_Size(pyIn));
+ convertPySequence(pyIn, PyLong_AsUnsignedLongLong, handle->data());
+}
+
+static PythonToCppFunc sequenceToCppUnsignedLongLongArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */)
+{
+ return intArrayCheck(pyIn, dim1) ? sequenceToCppUnsignedLongLongArray : nullptr;
+}
+
+// Float
+
+static inline bool floatCheck(PyObject *pyIn) { return PyFloat_Check(pyIn); }
+
+static inline bool floatArrayCheck(PyObject *pyIn, int expectedSize = -1)
+{
+ return PySequence_Check(pyIn) && sequenceAllOf(pyIn, floatCheck)
+ && sequenceSizeCheck(pyIn, expectedSize);
+}
+
+static void sequenceToCppDoubleArray(PyObject *pyIn, void *cppOut)
+{
+ ArrayHandle<double> *handle = reinterpret_cast<ArrayHandle<double> *>(cppOut);
+ handle->allocate(PySequence_Size(pyIn));
+ convertPySequence(pyIn, PyFloat_AsDouble, handle->data());
+}
+
+static inline float pyToFloat(PyObject *pyIn) { return float(PyFloat_AsDouble(pyIn)); }
+
+static void sequenceToCppFloatArray(PyObject *pyIn, void *cppOut)
+{
+ ArrayHandle<float> *handle = reinterpret_cast<ArrayHandle<float> *>(cppOut);
+ handle->allocate(PySequence_Size(pyIn));
+ convertPySequence(pyIn, pyToFloat, handle->data());
+}
+
+static PythonToCppFunc sequenceToCppFloatArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */)
+{
+ return floatArrayCheck(pyIn, dim1) ? sequenceToCppFloatArray : nullptr;
+}
+
+static PythonToCppFunc sequenceToCppDoubleArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */)
+{
+ return floatArrayCheck(pyIn, dim1) ? sequenceToCppDoubleArray : nullptr;
+}
+
+#ifdef HAVE_NUMPY
+void initNumPyArrayConverters();
+#endif
+
+void initArrayConverters()
+{
+ SbkArrayConverter **start = &ArrayTypeConverters[0][0];
+ std::fill(start, start + sizeof(ArrayTypeConverters) / sizeof(ArrayTypeConverters[0][0]), nullptr);
+ // Populate 1-dimensional sequence converters
+ ArrayTypeConverters[SBK_DOUBLE_ARRAY_IDX][0] =
+ createArrayConverter(sequenceToCppDoubleArrayCheck);
+ ArrayTypeConverters[SBK_FLOAT_ARRAY_IDX][0] =
+ createArrayConverter(sequenceToCppFloatArrayCheck);
+ ArrayTypeConverters[SBK_SHORT_ARRAY_IDX][0] =
+ createArrayConverter(sequenceToCppShortArrayCheck);
+ ArrayTypeConverters[SBK_UNSIGNEDSHORT_ARRAY_IDX][0] =
+ createArrayConverter(sequenceToCppUnsignedShortArrayCheck);
+ ArrayTypeConverters[SBK_INT_ARRAY_IDX][0] =
+ createArrayConverter(sequenceToCppIntArrayCheck);
+ ArrayTypeConverters[SBK_UNSIGNEDINT_ARRAY_IDX][0] =
+ createArrayConverter(sequenceToCppUnsignedArrayCheck);
+ ArrayTypeConverters[SBK_LONGLONG_ARRAY_IDX][0] =
+ createArrayConverter(sequenceToCppLongLongArrayCheck);
+ ArrayTypeConverters[SBK_UNSIGNEDLONGLONG_ARRAY_IDX][0] =
+ createArrayConverter(sequenceToCppUnsignedLongLongArrayCheck);
+
+#ifdef HAVE_NUMPY
+ initNumPyArrayConverters();
+#endif
+}
+
+SbkArrayConverter *arrayTypeConverter(int index, int dimension)
+{
+ SbkArrayConverter *c = ArrayTypeConverters[index][dimension - 1];
+ return c ? c : unimplementedArrayConverter();
+}
+
+// Internal, for usage by numpy
+void setArrayTypeConverter(int index, int dimension, SbkArrayConverter *c)
+{
+ ArrayTypeConverters[index][dimension - 1] = c;
+}
+
+} // namespace Conversions
+} // namespace Shiboken
diff --git a/sources/shiboken2/libshiboken/sbkarrayconverter.h b/sources/shiboken2/libshiboken/sbkarrayconverter.h
new file mode 100644
index 000000000..f3d3e5f98
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkarrayconverter.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef SBKARRAYCONVERTERS_H
+#define SBKARRAYCONVERTERS_H
+
+#include "sbkpython.h"
+#include "shibokenmacros.h"
+
+extern "C" {
+struct SbkArrayConverter;
+}
+
+namespace Shiboken {
+namespace Conversions {
+
+enum : int {
+ SBK_UNIMPLEMENTED_ARRAY_IDX,
+ SBK_DOUBLE_ARRAY_IDX,
+ SBK_FLOAT_ARRAY_IDX,
+ SBK_SHORT_ARRAY_IDX,
+ SBK_UNSIGNEDSHORT_ARRAY_IDX,
+ SBK_INT_ARRAY_IDX,
+ SBK_UNSIGNEDINT_ARRAY_IDX,
+ SBK_LONGLONG_ARRAY_IDX,
+ SBK_UNSIGNEDLONGLONG_ARRAY_IDX,
+ SBK_ARRAY_IDX_SIZE
+};
+
+/**
+ * ArrayHandle is the type expected by shiboken2's array converter
+ * functions. It provides access to array data which it may own
+ * (in the case of conversions from PySequence) or a flat pointer
+ * to internal data (in the case of array modules like numpy).
+ */
+
+template <class T>
+class ArrayHandle
+{
+ ArrayHandle(const ArrayHandle &) = delete;
+ ArrayHandle& operator=(const ArrayHandle &) = delete;
+public:
+ ArrayHandle() {}
+ ~ArrayHandle() { destroy(); }
+
+ void allocate(Py_ssize_t size);
+ void setData(T *d, size_t size);
+
+ size_t size() const { return m_size; }
+ T *data() const { return m_data; }
+ operator T*() const { return m_data; }
+
+private:
+ void destroy();
+
+ T *m_data = nullptr;
+ Py_ssize_t m_size = 0;
+ bool m_owned = false;
+};
+
+/**
+ * Similar to ArrayHandle for fixed size 2 dimensional arrays.
+ * columns is the size of the last dimension
+ * It only has a setData() methods since it will be used for numpy only.
+ */
+
+template <class T, int columns>
+class Array2Handle
+{
+public:
+ typedef T RowType[columns];
+
+ Array2Handle() {}
+
+ operator RowType*() const { return m_rows; }
+
+ void setData(RowType *d) { m_rows = d; }
+
+private:
+ RowType *m_rows = nullptr;
+};
+
+/// Returns the converter for an array type.
+LIBSHIBOKEN_API SbkArrayConverter *arrayTypeConverter(int index, int dimension = 1);
+
+template <class T>
+struct ArrayTypeIndex{
+ enum : int { index = SBK_UNIMPLEMENTED_ARRAY_IDX };
+};
+
+template <> struct ArrayTypeIndex<double> { enum : int { index = SBK_DOUBLE_ARRAY_IDX }; };
+template <> struct ArrayTypeIndex<float> { enum : int { index = SBK_FLOAT_ARRAY_IDX };};
+template <> struct ArrayTypeIndex<short> { enum : int { index = SBK_SHORT_ARRAY_IDX };};
+template <> struct ArrayTypeIndex<unsigned short> { enum : int { index = SBK_UNSIGNEDSHORT_ARRAY_IDX };};
+template <> struct ArrayTypeIndex<int> { enum : int { index = SBK_INT_ARRAY_IDX };};
+template <> struct ArrayTypeIndex<unsigned> { enum : int { index = SBK_UNSIGNEDINT_ARRAY_IDX };};
+template <> struct ArrayTypeIndex<long long> { enum : int { index = SBK_LONGLONG_ARRAY_IDX };};
+template <> struct ArrayTypeIndex<unsigned long long> { enum : int { index = SBK_UNSIGNEDLONGLONG_ARRAY_IDX };};
+
+template<typename T> SbkArrayConverter *ArrayTypeConverter(int dimension)
+{ return arrayTypeConverter(ArrayTypeIndex<T>::index, dimension); }
+
+// ArrayHandle methods
+template<class T>
+void ArrayHandle<T>::allocate(Py_ssize_t size)
+{
+ destroy();
+ m_data = new T[size];
+ m_size = size;
+ m_owned = true;
+}
+
+template<class T>
+void ArrayHandle<T>::setData(T *d, size_t size)
+{
+ destroy();
+ m_data = d;
+ m_size = size;
+ m_owned = false;
+}
+
+template<class T>
+void ArrayHandle<T>::destroy()
+{
+ if (m_owned)
+ delete [] m_data;
+ m_data = nullptr;
+ m_size = 0;
+ m_owned = false;
+}
+
+} // namespace Conversions
+} // namespace Shiboken
+
+#endif // SBKARRAYCONVERTERS_H
diff --git a/sources/shiboken2/libshiboken/sbkarrayconverter_p.h b/sources/shiboken2/libshiboken/sbkarrayconverter_p.h
new file mode 100644
index 000000000..9384fbcf5
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkarrayconverter_p.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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$
+**
+****************************************************************************/
+
+#ifndef SBKARRAYCONVERTER_P_H
+#define SBKARRAYCONVERTER_P_H
+
+#include "sbkconverter_p.h"
+#include <vector>
+
+extern "C"
+{
+
+typedef PythonToCppFunc (*IsArrayConvertibleToCppFunc)(PyObject*, int dim1, int dim2);
+/**
+ * \internal
+ * Private structure of SbkArrayConverter.
+ */
+
+struct SbkArrayConverter
+{
+ std::vector<IsArrayConvertibleToCppFunc> toCppConversions;
+};
+
+} // extern "C"
+
+#endif // SBKARRAYCONVERTER_P_H
diff --git a/sources/shiboken2/libshiboken/sbkconverter.cpp b/sources/shiboken2/libshiboken/sbkconverter.cpp
index 0949d803d..0e154da39 100644
--- a/sources/shiboken2/libshiboken/sbkconverter.cpp
+++ b/sources/shiboken2/libshiboken/sbkconverter.cpp
@@ -39,22 +39,26 @@
#include "sbkconverter.h"
#include "sbkconverter_p.h"
+#include "sbkarrayconverter_p.h"
#include "basewrapper_p.h"
#include "bindingmanager.h"
-#include "google/dense_hash_map"
#include "autodecref.h"
#include "sbkdbg.h"
#include "helper.h"
#include "voidptr.h"
+#include <unordered_map>
+
static SbkConverter** PrimitiveTypeConverters;
-typedef google::dense_hash_map<std::string, SbkConverter*> ConvertersMap;
+typedef std::unordered_map<std::string, SbkConverter *> ConvertersMap;
static ConvertersMap converters;
namespace Shiboken {
namespace Conversions {
+void initArrayConverters();
+
void init()
{
static SbkConverter* primitiveTypeConverters[] = {
@@ -79,8 +83,6 @@ void init()
PrimitiveTypeConverters = primitiveTypeConverters;
assert(converters.empty());
- converters.set_empty_key("");
- converters.set_deleted_key("?");
converters["PY_LONG_LONG"] = primitiveTypeConverters[SBK_PY_LONG_LONG_IDX];
converters["bool"] = primitiveTypeConverters[SBK_BOOL_IDX_1];
converters["char"] = primitiveTypeConverters[SBK_CHAR_IDX];
@@ -98,9 +100,11 @@ void init()
converters["unsigned long"] = primitiveTypeConverters[SBK_UNSIGNEDLONG_IDX];
converters["unsigned short"] = primitiveTypeConverters[SBK_UNSIGNEDSHORT_IDX];
converters["void*"] = primitiveTypeConverters[SBK_VOIDPTR_IDX];
+
+ initArrayConverters();
}
-static SbkConverter* createConverterObject(PyTypeObject* type,
+SbkConverter *createConverterObject(PyTypeObject *type,
PythonToCppFunc toCppPointerConvFunc,
IsConvertibleToCppFunc toCppPointerCheckFunc,
CppToPythonFunc pointerToPythonFunc,
@@ -257,6 +261,17 @@ PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject
return IsPythonToCppConvertible(converter, pyIn);
}
+PythonToCppFunc isPythonToCppConvertible(const SbkArrayConverter *converter,
+ int dim1, int dim2, PyObject *pyIn)
+{
+ assert(pyIn);
+ for (IsArrayConvertibleToCppFunc f : converter->toCppConversions) {
+ if (PythonToCppFunc c = f(pyIn, dim1, dim2))
+ return c;
+ }
+ return nullptr;
+}
+
PythonToCppFunc isPythonToCppReferenceConvertible(const SbkObjectType *type, PyObject *pyIn)
{
if (pyIn != Py_None) {
diff --git a/sources/shiboken2/libshiboken/sbkconverter.h b/sources/shiboken2/libshiboken/sbkconverter.h
index 7eb666b25..6d40f85cc 100644
--- a/sources/shiboken2/libshiboken/sbkconverter.h
+++ b/sources/shiboken2/libshiboken/sbkconverter.h
@@ -67,6 +67,7 @@ extern "C"
* using the functions provided by the converter API.
*/
struct SbkConverter;
+struct SbkArrayConverter;
/**
* Given a void pointer to a C++ object, this function must return
@@ -241,6 +242,8 @@ LIBSHIBOKEN_API PythonToCppFunc isPythonToCppReferenceConvertible(const SbkObjec
/// This is the same as isPythonToCppValueConvertible function.
LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn);
+LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(const SbkArrayConverter *converter,
+ int dim1, int dim2, PyObject *pyIn);
/**
* Returns the C++ pointer for the \p pyIn object cast to the type passed via \p desiredType.
diff --git a/sources/shiboken2/libshiboken/sbkconverter_p.h b/sources/shiboken2/libshiboken/sbkconverter_p.h
index 110358273..cfe3d7e98 100644
--- a/sources/shiboken2/libshiboken/sbkconverter_p.h
+++ b/sources/shiboken2/libshiboken/sbkconverter_p.h
@@ -533,4 +533,13 @@ struct Primitive<std::string> : TwoPrimitive<std::string>
}
};
+namespace Shiboken {
+namespace Conversions {
+SbkConverter *createConverterObject(PyTypeObject *type,
+ PythonToCppFunc toCppPointerConvFunc,
+ IsConvertibleToCppFunc toCppPointerCheckFunc,
+ CppToPythonFunc pointerToPythonFunc,
+ CppToPythonFunc copyToPythonFunc);
+} // namespace Conversions
+} // namespace Shiboken
#endif // SBK_CONVERTER_P_H
diff --git a/sources/shiboken2/libshiboken/sbkenum.cpp b/sources/shiboken2/libshiboken/sbkenum.cpp
index a62448aa6..c817a21de 100644
--- a/sources/shiboken2/libshiboken/sbkenum.cpp
+++ b/sources/shiboken2/libshiboken/sbkenum.cpp
@@ -492,11 +492,11 @@ bool createGlobalEnumItem(PyTypeObject* enumType, PyObject* module, const char*
return false;
}
-bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const char* itemName, long itemValue)
+bool createScopedEnumItem(PyTypeObject *enumType, PyTypeObject *scope,
+ const char *itemName, long itemValue)
{
- PyObject* enumItem = createEnumItem(enumType, itemName, itemValue);
- if (enumItem) {
- if (PyDict_SetItemString(scope->super.ht_type.tp_dict, itemName, enumItem) < 0)
+ if (PyObject *enumItem = createEnumItem(enumType, itemName, itemValue)) {
+ if (PyDict_SetItemString(scope->tp_dict, itemName, enumItem) < 0)
return false;
Py_DECREF(enumItem);
return true;
@@ -504,6 +504,11 @@ bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const ch
return false;
}
+bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const char* itemName, long itemValue)
+{
+ return createScopedEnumItem(enumType, &scope->super.ht_type, itemName, itemValue);
+}
+
PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName)
{
bool newValue = true;
diff --git a/sources/shiboken2/libshiboken/sbkenum.h b/sources/shiboken2/libshiboken/sbkenum.h
index 4b572dbcc..b01114ba6 100644
--- a/sources/shiboken2/libshiboken/sbkenum.h
+++ b/sources/shiboken2/libshiboken/sbkenum.h
@@ -95,6 +95,8 @@ namespace Enum
*/
LIBSHIBOKEN_API bool createGlobalEnumItem(PyTypeObject* enumType, PyObject* module, const char* itemName, long itemValue);
/// This function does the same as createGlobalEnumItem, but adds the enum to a Shiboken type or namespace.
+ LIBSHIBOKEN_API bool createScopedEnumItem(PyTypeObject *enumType, PyTypeObject *scope,
+ const char *itemName, long itemValue);
LIBSHIBOKEN_API bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const char* itemName, long itemValue);
LIBSHIBOKEN_API PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName = 0);
diff --git a/sources/shiboken2/libshiboken/sbkmodule.cpp b/sources/shiboken2/libshiboken/sbkmodule.cpp
index 084e23efa..2ea9d56ac 100644
--- a/sources/shiboken2/libshiboken/sbkmodule.cpp
+++ b/sources/shiboken2/libshiboken/sbkmodule.cpp
@@ -40,17 +40,13 @@
#include "sbkmodule.h"
#include "basewrapper.h"
#include "bindingmanager.h"
-
-// TODO: for performance reasons this should be a sparse_hash_map,
-// because there'll be very few modules as keys. The sparse_hash_map
-// is missing from the code added in ../ext/sparsehash/google directory.
-#include "google/dense_hash_map"
+#include <unordered_map>
/// This hash maps module objects to arrays of Python types.
-typedef google::dense_hash_map<PyObject*, PyTypeObject**> ModuleTypesMap;
+typedef std::unordered_map<PyObject *, PyTypeObject **> ModuleTypesMap;
/// This hash maps module objects to arrays of converters.
-typedef google::dense_hash_map<PyObject*, SbkConverter**> ModuleConvertersMap;
+typedef std::unordered_map<PyObject *, SbkConverter **> ModuleConvertersMap;
/// All types produced in imported modules are mapped here.
static ModuleTypesMap moduleTypes;
@@ -61,15 +57,6 @@ namespace Shiboken
namespace Module
{
-void init()
-{
- // Initializes type registry for modules.
- moduleTypes.set_empty_key((ModuleTypesMap::key_type)0);
- moduleTypes.set_deleted_key((ModuleTypesMap::key_type)1);
- moduleConverters.set_empty_key((ModuleConvertersMap::key_type)0);
- moduleConverters.set_deleted_key((ModuleConvertersMap::key_type)1);
-}
-
PyObject* import(const char* moduleName)
{
PyObject* sysModules = PyImport_GetModuleDict();
diff --git a/sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp b/sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp
new file mode 100644
index 000000000..97eab2205
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp
@@ -0,0 +1,308 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 "sbkarrayconverter.h"
+#include "helper.h"
+#include "sbkconverter.h"
+#include "sbkconverter_p.h"
+#include "sbkarrayconverter_p.h"
+
+#include <numpy/arrayobject.h>
+
+#include <algorithm>
+#include <iostream>
+#include <cstdint>
+
+enum { debugNumPy = 0 };
+
+struct TypeCharMapping
+{
+ NPY_TYPES type;
+ const char *name;
+};
+
+static const TypeCharMapping typeCharMappings[] = {
+{NPY_BYTE, "NPY_BYTE"},
+{NPY_UBYTE, "NPY_UBYTE"},
+{NPY_SHORT, "NPY_SHORT"},
+{NPY_USHORT, "NPY_USHORT"},
+{NPY_INT, "NPY_INT"},
+{NPY_UINT, "NPY_UINT"},
+{NPY_LONG, "NPY_LONG"},
+{NPY_ULONG, "NPY_ULONG"},
+{NPY_LONGLONG, "NPY_LONGLONG"},
+{NPY_ULONGLONG, "NPY_ULONGLONG"},
+{NPY_FLOAT, "NPY_FLOAT"},
+{NPY_DOUBLE, "NPY_DOUBLE"}
+};
+
+const char *npTypeName(npy_intp t)
+{
+ const TypeCharMapping *end = typeCharMappings + sizeof(typeCharMappings) / sizeof(typeCharMappings[0]);
+ const TypeCharMapping *result =
+ std::find_if(typeCharMappings, end,
+ [t] (const TypeCharMapping &m) { return m.type == t; });
+ return result != end ? result->name : nullptr;
+}
+
+std::ostream &operator<<(std::ostream &str, PyArrayObject *o)
+{
+ str << "PyArrayObject(";
+ if (o) {
+ const npy_intp npType = PyArray_TYPE(o);
+ if (const char *name = npTypeName(npType))
+ str << name;
+ else
+ str << "type=" << npType;
+ const int nDim = PyArray_NDIM(o);
+ const npy_intp *dims = PyArray_DIMS(o);
+ for (int d = 0; d < nDim; ++d)
+ str << '[' << dims[d] << ']';
+ str << ", ";
+ const int flags = PyArray_FLAGS(o);
+ if ((flags & NPY_ARRAY_C_CONTIGUOUS) != 0)
+ str << " NPY_ARRAY_C_CONTIGUOUS";
+ if ((flags & NPY_ARRAY_F_CONTIGUOUS) != 0)
+ str << " NPY_ARRAY_F_CONTIGUOUS";
+ if ((flags & NPY_ARRAY_OWNDATA) != 0)
+ str << " NPY_ARRAY_OWNDATA";
+ if ((flags & NPY_ARRAY_FORCECAST) != 0)
+ str << " NPY_ARRAY_FORCECAST";
+ if ((flags & NPY_ARRAY_ENSURECOPY) != 0)
+ str << " NPY_ARRAY_ENSURECOPY";
+ if ((flags & NPY_ARRAY_ENSUREARRAY) != 0)
+ str << " NPY_ARRAY_ENSUREARRAY";
+ if ((flags & NPY_ARRAY_ELEMENTSTRIDES) != 0)
+ str << " NPY_ARRAY_ELEMENTSTRIDES";
+ if ((flags & NPY_ARRAY_ALIGNED) != 0)
+ str << " NPY_ARRAY_ALIGNED";
+ if ((flags & NPY_ARRAY_NOTSWAPPED) != 0)
+ str << " NPY_ARRAY_NOTSWAPPED";
+ if ((flags & NPY_ARRAY_WRITEABLE) != 0)
+ str << " NPY_ARRAY_WRITEABLE";
+ if ((flags & NPY_ARRAY_UPDATEIFCOPY) != 0)
+ str << " NPY_ARRAY_UPDATEIFCOPY";
+ } else {
+ str << '0';
+ }
+ str << ')';
+ return str;
+}
+
+namespace Shiboken {
+namespace Conversions {
+
+// Internals from sbkarrayconverter.cpp
+SbkArrayConverter *createArrayConverter(IsArrayConvertibleToCppFunc toCppCheckFunc);
+void setArrayTypeConverter(int index, int dimension, SbkArrayConverter *c);
+SbkArrayConverter *unimplementedArrayConverter();
+
+template <int dimension>
+static bool isPrimitiveArray(PyObject *pyIn, int expectedNpType)
+{
+ if (!PyArray_Check(pyIn))
+ return false;
+ PyArrayObject *pya = reinterpret_cast<PyArrayObject *>(pyIn);
+ if (debugNumPy) {
+ std::cerr << __FUNCTION__ << "(expectedNpType=" << expectedNpType;
+ if (const char *name = npTypeName(expectedNpType))
+ std::cerr << " (" << name << ')';
+ std::cerr << ' ' << pya << '\n';
+ }
+
+ const int dim = PyArray_NDIM(pya);
+ if (dim != dimension) {
+ warning(PyExc_RuntimeWarning, 0,
+ "%d dimensional numpy array passed to a function expecting a %d dimensional array.",
+ dim, dimension);
+ return false;
+ }
+ if ((PyArray_FLAGS(pya) & NPY_ARRAY_C_CONTIGUOUS) == 0) {
+ warning(PyExc_RuntimeWarning, 0,
+ "Cannot handle numpy arrays that do not have NPY_ARRAY_C_CONTIGUOUS set.");
+ return false;
+ }
+ const int actualNpType = PyArray_TYPE(pya);
+ if (actualNpType != expectedNpType) {
+ const char *actualName = npTypeName(actualNpType);
+ const char *expectedName = npTypeName(expectedNpType);
+ warning(PyExc_RuntimeWarning, 0,
+ "A numpy array of type %d (%s) was passed to a function expecting type %d (%s).",
+ actualNpType, actualName ? actualName : "",
+ expectedNpType, expectedName ? expectedName : "");
+ return false;
+ }
+ return true;
+}
+
+static inline bool primitiveArrayCheck1(PyObject *pyIn, int expectedNpType, int expectedSize)
+{
+ if (!isPrimitiveArray<1>(pyIn, expectedNpType))
+ return false;
+ if (expectedSize >= 0) {
+ PyArrayObject *pya = reinterpret_cast<PyArrayObject *>(pyIn);
+ const int size = int(PyArray_DIMS(pya)[0]);
+ if (size < expectedSize) {
+ warning(PyExc_RuntimeWarning, 0, "A numpy array of size %d was passed to a function expects %d.",
+ size, expectedSize);
+ return false;
+ }
+ }
+ return true;
+}
+
+// Convert one-dimensional array
+template <class T>
+static void convertArray1(PyObject *pyIn, void *cppOut)
+{
+ ArrayHandle<T> *handle = reinterpret_cast<ArrayHandle<T> *>(cppOut);
+ PyArrayObject *pya = reinterpret_cast<PyArrayObject *>(pyIn);
+ const npy_intp size = PyArray_DIMS(pya)[0];
+ if (debugNumPy)
+ std::cerr << __FUNCTION__ << ' ' << size << '\n';
+ handle->setData(reinterpret_cast<T *>(PyArray_DATA(pya)), size_t(size));
+}
+
+// Convert 2 dimensional array
+template <class T>
+static void convertArray2(PyObject *pyIn, void *cppOut)
+{
+ typedef typename Array2Handle<T, 1>::RowType RowType;
+ Array2Handle<T, 1> *handle = reinterpret_cast<Array2Handle<T, 1> *>(cppOut);
+ PyArrayObject *pya = reinterpret_cast<PyArrayObject *>(pyIn);
+ handle->setData(reinterpret_cast<RowType *>(PyArray_DATA(pya)));
+}
+
+template <class T, int NumPyType>
+static PythonToCppFunc checkArray1(PyObject *pyIn, int dim1, int /* dim2 */)
+{
+ return primitiveArrayCheck1(pyIn, NumPyType, dim1) ? convertArray1<T> : nullptr;
+}
+
+static inline bool primitiveArrayCheck2(PyObject *pyIn, int expectedNpType, int expectedDim1, int expectedDim2)
+{
+ if (!isPrimitiveArray<2>(pyIn, expectedNpType))
+ return false;
+ if (expectedDim2 >= 0) {
+ PyArrayObject *pya = reinterpret_cast<PyArrayObject *>(pyIn);
+ const int dim1 = int(PyArray_DIMS(pya)[0]);
+ const int dim2 = int(PyArray_DIMS(pya)[1]);
+ if (dim1 != expectedDim1 || dim2 != expectedDim2) {
+ warning(PyExc_RuntimeWarning, 0, "A numpy array of size %dx%d was passed to a function that expects %dx%d.",
+ dim1, dim2, expectedDim1, expectedDim2);
+ return false;
+ }
+ }
+ return true;
+}
+
+template <class T, int NumPyType>
+static PythonToCppFunc checkArray2(PyObject *pyIn, int dim1, int dim2)
+{
+ return primitiveArrayCheck2(pyIn, NumPyType, dim1, dim2) ? convertArray2<T> : nullptr;
+}
+
+template <class T>
+static void setOrExtendArrayConverter(int dimension, IsArrayConvertibleToCppFunc toCppCheckFunc)
+{
+ SbkArrayConverter *arrayConverter = ArrayTypeConverter<T>(dimension);
+ if (arrayConverter == unimplementedArrayConverter()) {
+ arrayConverter = createArrayConverter(toCppCheckFunc);
+ setArrayTypeConverter(ArrayTypeIndex<T>::index, dimension, arrayConverter);
+ } else {
+ arrayConverter->toCppConversions.push_back(toCppCheckFunc);
+ }
+}
+
+// Extend the converters for primitive type one-dimensional arrays by NumPy ones.
+template <class T, int NumPyType>
+static inline void extendArrayConverter1()
+{
+ setOrExtendArrayConverter<T>(1, checkArray1<T, NumPyType>);
+}
+
+// Extend the converters for primitive type one-dimensional arrays by NumPy ones.
+template <class T, int NumPyType>
+static inline void extendArrayConverter2()
+{
+ setOrExtendArrayConverter<T>(2, checkArray2<T, NumPyType>);
+}
+
+void initNumPyArrayConverters()
+{
+ // Expanded from macro "import_array" in __multiarray_api.h
+ // Make sure to read about the magic defines PY_ARRAY_UNIQUE_SYMBOL etc.,
+ // when changing this or spreading the code over several source files.
+ if (_import_array() < 0) {
+ if (debugNumPy)
+ PyErr_Print();
+ PyErr_Clear();
+ return;
+ }
+ // Extend the converters for primitive types by NumPy ones.
+ extendArrayConverter1<short, NPY_SHORT>();
+ extendArrayConverter2<short, NPY_SHORT>();
+ extendArrayConverter1<unsigned short, NPY_SHORT>();
+ extendArrayConverter2<unsigned short, NPY_SHORT>();
+ extendArrayConverter1<int, NPY_INT>();
+ extendArrayConverter2<int, NPY_INT>();
+ extendArrayConverter1<unsigned int, NPY_UINT>();
+ extendArrayConverter2<unsigned int, NPY_UINT>();
+ extendArrayConverter1<long long, NPY_LONGLONG>();
+ extendArrayConverter2<long long, NPY_LONGLONG>();
+ extendArrayConverter1<unsigned long long, NPY_ULONGLONG>();
+ if (sizeof(long) == 8) { // UNIX/LP64: ints typically come as long
+ extendArrayConverter1<long long, NPY_LONG>();
+ extendArrayConverter2<long long, NPY_LONG>();
+ extendArrayConverter1<unsigned long long, NPY_ULONG>();
+ extendArrayConverter2<unsigned long long, NPY_ULONG>();
+ } else if (sizeof(long) == sizeof(int)) {
+ extendArrayConverter1<int, NPY_LONG>();
+ extendArrayConverter1<unsigned, NPY_ULONG>();
+ extendArrayConverter2<int, NPY_LONG>();
+ extendArrayConverter2<unsigned, NPY_ULONG>();
+ }
+ extendArrayConverter1<float, NPY_FLOAT>();
+ extendArrayConverter2<float, NPY_FLOAT>();
+ extendArrayConverter1<double, NPY_DOUBLE>();
+ extendArrayConverter2<double, NPY_DOUBLE>();
+}
+
+} // namespace Conversions
+} // namespace Shiboken
diff --git a/sources/shiboken2/libshiboken/shiboken.h b/sources/shiboken2/libshiboken/shiboken.h
index 9f4b8a560..6cdfe65bd 100644
--- a/sources/shiboken2/libshiboken/shiboken.h
+++ b/sources/shiboken2/libshiboken/shiboken.h
@@ -47,6 +47,7 @@
#include "gilstate.h"
#include "threadstatesaver.h"
#include "helper.h"
+#include "sbkarrayconverter.h"
#include "sbkconverter.h"
#include "sbkenum.h"
#include "sbkmodule.h"