aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2017-08-22 13:36:42 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2017-08-22 13:36:45 +0200
commit5495989aa1b0161512cc1f73cb0e3a3deb1cf4d1 (patch)
tree4a6d78b6927cb636f0b34650e4d8508f3729c762
parent2c6b753b9e2d262477c7171116d5f97d26698001 (diff)
parentecef77d751369cf7d66d5fccd110a30237755cdc (diff)
Merge remote-tracking branch 'origin/5.9' into dev
m---------sources/pyside2-tools0
-rw-r--r--sources/pyside2/CMakeLists.txt46
-rw-r--r--sources/pyside2/PySide2/QtCore/CMakeLists.txt2
-rw-r--r--sources/pyside2/PySide2/QtCore/typesystem_core_common.xml6
-rw-r--r--sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml4
-rw-r--r--sources/pyside2/PySide2/QtMultimedia/typesystem_multimedia_common.xml2
-rw-r--r--sources/pyside2/PySide2/QtOpenGL/typesystem_opengl.xml12
-rw-r--r--sources/pyside2/PySide2/QtTest/typesystem_test.xml1
-rw-r--r--sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml4
-rw-r--r--sources/pyside2/PySide2/__init__.py.in4
-rw-r--r--sources/pyside2/tests/QtCore/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/QtCore/qtimezone_test.py43
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp114
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h5
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp48
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h5
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h1
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp39
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testarrayargument.h1
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.cpp13
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.h5
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem_p.h1
-rw-r--r--sources/shiboken2/generator/generator.cpp9
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp30
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp31
-rw-r--r--sources/shiboken2/libshiboken/CMakeLists.txt35
-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.cpp18
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter.h3
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter_p.h10
-rw-r--r--sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp308
-rw-r--r--sources/shiboken2/libshiboken/shiboken.h1
-rw-r--r--sources/shiboken2/tests/libsample/functions.cpp41
-rw-r--r--sources/shiboken2/tests/libsample/functions.h11
-rw-r--r--sources/shiboken2/tests/samplebinding/CMakeLists.txt1
-rw-r--r--sources/shiboken2/tests/samplebinding/array_numpy_test.py64
-rw-r--r--sources/shiboken2/tests/samplebinding/array_sequence_test.py53
-rw-r--r--sources/shiboken2/tests/samplebinding/typesystem_sample.xml14
40 files changed, 1439 insertions, 69 deletions
diff --git a/sources/pyside2-tools b/sources/pyside2-tools
-Subproject f68388cf547c0d63a5d4a145f65aa9fa90529d5
+Subproject 413ecc73fbe6d6717ae2132e86648ac8b6da9d3
diff --git a/sources/pyside2/CMakeLists.txt b/sources/pyside2/CMakeLists.txt
index d5a12379b..d517d0ad7 100644
--- a/sources/pyside2/CMakeLists.txt
+++ b/sources/pyside2/CMakeLists.txt
@@ -171,6 +171,52 @@ else()
CACHE STRING "PySide version [full]" FORCE)
endif()
+string(TIMESTAMP PYSIDE_BUILD_DATE "%Y-%m-%dT%H:%M:%S+00:00" UTC)
+if (PYSIDE_BUILD_DATE)
+ set(PYSIDE_BUILD_DATE "__build_date__ = '${PYSIDE_BUILD_DATE}'")
+endif()
+
+find_package(Git)
+if(GIT_FOUND)
+ # Check if current source folder is inside a git repo, so that commit information can be
+ # queried.
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} rev-parse --git-dir
+ OUTPUT_VARIABLE PYSIDE_SOURCE_IS_INSIDE_REPO
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ if(PYSIDE_SOURCE_IS_INSIDE_REPO)
+ # Force git dates to be UTC-based.
+ set(ENV{TZ} UTC)
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} --no-pager show --date=format-local:%Y-%m-%dT%H:%M:%S+00:00 -s --format=%cd HEAD
+ OUTPUT_VARIABLE PYSIDE_BUILD_COMMIT_DATE
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(PYSIDE_BUILD_COMMIT_DATE)
+ set(PYSIDE_BUILD_COMMIT_DATE "__build_commit_date__ = '${PYSIDE_BUILD_COMMIT_DATE}'")
+ endif()
+ unset(ENV{TZ})
+
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} rev-parse HEAD
+ OUTPUT_VARIABLE PYSIDE_BUILD_COMMIT_HASH
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(PYSIDE_BUILD_COMMIT_HASH)
+ set(PYSIDE_BUILD_COMMIT_HASH "__build_commit_hash__ = '${PYSIDE_BUILD_COMMIT_HASH}'")
+ endif()
+
+ execute_process(
+ COMMAND ${GIT_EXECUTABLE} describe HEAD
+ OUTPUT_VARIABLE PYSIDE_BUILD_COMMIT_HASH_DESCRIBED
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(PYSIDE_BUILD_COMMIT_HASH_DESCRIBED)
+ set(PYSIDE_BUILD_COMMIT_HASH_DESCRIBED "__build_commit_hash_described__ = '${PYSIDE_BUILD_COMMIT_HASH_DESCRIBED}'")
+ endif()
+
+ endif()
+endif()
+
include(PySideModules)
macro(COLLECT_MODULE_IF_FOUND shortname)
diff --git a/sources/pyside2/PySide2/QtCore/CMakeLists.txt b/sources/pyside2/PySide2/QtCore/CMakeLists.txt
index afef603c7..0439f0a5c 100644
--- a/sources/pyside2/PySide2/QtCore/CMakeLists.txt
+++ b/sources/pyside2/PySide2/QtCore/CMakeLists.txt
@@ -136,6 +136,8 @@ ${QtCore_GEN_DIR}/qtime_wrapper.cpp
${QtCore_GEN_DIR}/qtimeline_wrapper.cpp
${QtCore_GEN_DIR}/qtimer_wrapper.cpp
${QtCore_GEN_DIR}/qtimerevent_wrapper.cpp
+${QtCore_GEN_DIR}/qtimezone_wrapper.cpp
+${QtCore_GEN_DIR}/qtimezone_offsetdata_wrapper.cpp
${QtCore_GEN_DIR}/qtranslator_wrapper.cpp
${QtCore_GEN_DIR}/qurl_wrapper.cpp
${QtCore_GEN_DIR}/qurlquery_wrapper.cpp
diff --git a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml
index b8e070788..efcc5d955 100644
--- a/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml
+++ b/sources/pyside2/PySide2/QtCore/typesystem_core_common.xml
@@ -1787,6 +1787,12 @@
</modify-function>
</value-type>
+ <value-type name="QTimeZone">
+ <enum-type name="TimeType"/>
+ <enum-type name="NameType"/>
+ <value-type name="OffsetData"/>
+ </value-type>
+
<!-- FIXME QT5: Remove QUuid because cyclic dependency found on overloaddata QUuid(),
this lead to cyclic dependency in <<(QDataStream &, QUUid) and incorrect QDataStream code generation (Windows only)-->
<!-- <value-type name="QUuid">
diff --git a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml
index 0d9b56edd..343b76229 100644
--- a/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml
+++ b/sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml
@@ -639,7 +639,7 @@
%0 = new %TYPE(QPixmap::fromImage(%1));
</inject-code>
</add-function>
- <modify-function signature="QPixmap(const char **)">
+ <modify-function signature="QPixmap(const char*[])">
<modify-argument index="1">
<replace-type modified-type="PySequence" />
</modify-argument>
@@ -868,7 +868,7 @@
<modify-function signature="QImage(const uchar*,int,int,QImage::Format,QImageCleanupFunction, void *)" remove="all" />
<!-- ### -->
- <modify-function signature="QImage(const char**)">
+ <modify-function signature="QImage(const char*[])">
<modify-argument index="1">
<replace-type modified-type="PySequence" />
</modify-argument>
diff --git a/sources/pyside2/PySide2/QtMultimedia/typesystem_multimedia_common.xml b/sources/pyside2/PySide2/QtMultimedia/typesystem_multimedia_common.xml
index 9565b4334..f708d46ab 100644
--- a/sources/pyside2/PySide2/QtMultimedia/typesystem_multimedia_common.xml
+++ b/sources/pyside2/PySide2/QtMultimedia/typesystem_multimedia_common.xml
@@ -77,7 +77,7 @@
</modify-function>
-->
<!-- TODO: PYSIDE-354, arrays are not supported -->
- <modify-function signature="mapPlanes(QAbstractVideoBuffer::MapMode,int*,Array,Array)" remove="all"/>
+ <modify-function signature="mapPlanes(QAbstractVideoBuffer::MapMode,int*,int[4],uchar*[4])" remove="all"/>
</object-type>
<object-type name="QAbstractVideoSurface">
<enum-type name="Error"/>
diff --git a/sources/pyside2/PySide2/QtOpenGL/typesystem_opengl.xml b/sources/pyside2/PySide2/QtOpenGL/typesystem_opengl.xml
index d5c701b6f..8dea5d67c 100644
--- a/sources/pyside2/PySide2/QtOpenGL/typesystem_opengl.xml
+++ b/sources/pyside2/PySide2/QtOpenGL/typesystem_opengl.xml
@@ -59,6 +59,16 @@
<rejection class="QGLColormap::QGLColormapData"/>
<rejection class="QGLContext" field-name="currentCtx"/>
+ <rejection class="^QGL.*$" argument-type="^GLboolean( const)?\*$"/>
+ <rejection class="^QGL.*$" argument-type="^GLchar( const)?\*$"/>
+ <rejection class="^QGL.*$" argument-type="GLchar *const const*"/>
+ <rejection class="^QGL.*$" argument-type="^GLenum( const)?\*$"/>
+ <rejection class="^QGL.*$" argument-type="^GLfloat( const)?\*$"/>
+ <rejection class="^QGL.*$" argument-type="^GLfloat( const)?\[.*$"/>
+ <rejection class="^QGL.*$" argument-type="^GLdouble( const)?\*$"/>
+ <rejection class="^QGL.*$" argument-type="GLintptr"/>
+ <rejection class="^QGL.*$" argument-type="^GLint64( const)?\*$"/>
+ <rejection class="^QGL.*$" argument-type="^GLsizei( const)?\*$"/>
<namespace-type name="QGL">
<enum-type name="FormatOption" flags="FormatOptions" force-integer="yes"/>
@@ -681,8 +691,6 @@
<!-- ### -->
<!-- ### Use QMatrixZxY overloads -->
- <modify-function signature="setUniformValue(int,Array)" remove="all" />
- <modify-function signature="setUniformValue(const char*,Array)" remove="all" />
<modify-function signature="setAttributeValue(int,const GLfloat*,int,int)" remove="all" />
<modify-function signature="setAttributeValue(const char*,const GLfloat*,int,int)" remove="all" />
<modify-function signature="setAttributeArray(int, GLenum, const void*, int, int)" remove="all" since="4.7" />
diff --git a/sources/pyside2/PySide2/QtTest/typesystem_test.xml b/sources/pyside2/PySide2/QtTest/typesystem_test.xml
index 2c45ab3da..b30a6b5da 100644
--- a/sources/pyside2/PySide2/QtTest/typesystem_test.xml
+++ b/sources/pyside2/PySide2/QtTest/typesystem_test.xml
@@ -51,6 +51,7 @@
<rejection class="QTest" function-name="qCompare&lt;double,qreal&gt;"/>
<rejection class="QTest" function-name="qCompare&lt;qreal,double&gt;"/>
<rejection class="QTest" function-name="qCompare"/>
+ <rejection class="QTest" function-name="qInit"/>
<rejection class="QTest" function-name="qVerify"/>
<rejection class="QTest" function-name="qSleep"/>
<rejection class="QTest" function-name="toHexRepresentation"/>
diff --git a/sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml b/sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml
index 59412699c..7c16781c8 100644
--- a/sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml
+++ b/sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml
@@ -1576,7 +1576,7 @@
</modify-function>
<!-- TODO: Support conversions on virtual function -->
- <modify-function signature="drawItems(QPainter*, int, QGraphicsItem**, const QStyleOptionGraphicsItem*)">
+ <modify-function signature="drawItems(QPainter*, int, QGraphicsItem*[], const QStyleOptionGraphicsItem[])">
<modify-argument index="2">
<remove-argument/>
<conversion-rule class="native">
@@ -1688,7 +1688,7 @@
<enum-type name="SceneLayer" flags="SceneLayers"/>
<!-- Qt5: note: this was called 'obsolete'. Is that true? -->
- <modify-function signature="drawItems(QPainter*,int,QGraphicsItem**,const QStyleOptionGraphicsItem*,QWidget*)" remove="all" />
+ <modify-function signature="drawItems(QPainter*,int,QGraphicsItem*[],const QStyleOptionGraphicsItem[],QWidget*)" remove="all" />
<modify-function signature="createItemGroup(const QList&lt;QGraphicsItem*&gt;&amp;)">
<modify-argument index="1">
diff --git a/sources/pyside2/PySide2/__init__.py.in b/sources/pyside2/PySide2/__init__.py.in
index 99deb35e2..ffe017587 100644
--- a/sources/pyside2/PySide2/__init__.py.in
+++ b/sources/pyside2/PySide2/__init__.py.in
@@ -4,6 +4,10 @@ __all__ = list("Qt" + body for body in
__version__ = "@BINDING_API_VERSION_FULL@"
__version_info__ = (@BINDING_API_MAJOR_VERSION@, @BINDING_API_MINOR_VERSION@, @BINDING_API_MICRO_VERSION@, "@BINDING_API_RELEASE_LEVEL@", @BINDING_API_SERIAL@)
+@PYSIDE_BUILD_DATE@
+@PYSIDE_BUILD_COMMIT_DATE@
+@PYSIDE_BUILD_COMMIT_HASH@
+@PYSIDE_BUILD_COMMIT_HASH_DESCRIBED@
def _setupQtDirectories():
import sys
diff --git a/sources/pyside2/tests/QtCore/CMakeLists.txt b/sources/pyside2/tests/QtCore/CMakeLists.txt
index f7eb86d16..b8b0ec143 100644
--- a/sources/pyside2/tests/QtCore/CMakeLists.txt
+++ b/sources/pyside2/tests/QtCore/CMakeLists.txt
@@ -102,6 +102,7 @@ PYSIDE_TEST(qthread_signal_test.py)
PYSIDE_TEST(qthread_test.py)
PYSIDE_TEST(qtimer_singleshot_test.py)
PYSIDE_TEST(qtimer_timeout_test.py)
+PYSIDE_TEST(qtimezone_test.py)
PYSIDE_TEST(qtnamespace_test.py)
PYSIDE_TEST(qurl_test.py)
PYSIDE_TEST(qurlquery_test.py)
diff --git a/sources/pyside2/tests/QtCore/qtimezone_test.py b/sources/pyside2/tests/QtCore/qtimezone_test.py
new file mode 100644
index 000000000..e0bebdfbf
--- /dev/null
+++ b/sources/pyside2/tests/QtCore/qtimezone_test.py
@@ -0,0 +1,43 @@
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of PySide2.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## 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 General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## 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-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+import unittest
+
+from PySide2.QtCore import QTimeZone
+
+class TestQTimeZone (unittest.TestCase):
+ def testTimeZone(self):
+ id = 'Europe/Berlin'
+ timeZone = QTimeZone(id)
+ self.assertTrue(timeZone.isValid())
+ self.assertEqual(timeZone.id(), id)
+ name = timeZone.displayName(QTimeZone.GenericTime, QTimeZone.DefaultName)
+ self.assertTrue(name)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
index afdc84e46..5739643f2 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -1990,7 +1990,8 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu
}
metaFunction->setOriginalAttributes(metaFunction->attributes());
- fixArgumentNames(metaFunction);
+ if (!metaArguments.isEmpty())
+ fixArgumentNames(metaFunction, metaFunction->modifications(m_currentClass));
if (metaClass) {
const AbstractMetaArgumentList fargs = metaFunction->arguments();
@@ -2018,11 +2019,8 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu
return metaFunction;
}
-void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func)
+void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func, const FunctionModificationList &mods)
{
- if (func->arguments().isEmpty())
- return;
- const FunctionModificationList &mods = func->modifications(m_currentClass);
for (const FunctionModification &mod : mods) {
for (const ArgumentModification &argMod : mod.argument_mods) {
if (!argMod.renamed_to.isEmpty()) {
@@ -2108,6 +2106,44 @@ static inline AbstractMetaFunction::FunctionType functionTypeFromCodeModel(CodeM
return result;
}
+static inline QString msgCannotSetArrayUsage(const QString &function, int i, const QString &reason)
+{
+ return function + QLatin1String(": Cannot use parameter ") + QString::number(i + 1)
+ + QLatin1String(" as an array: ") + reason;
+}
+
+bool AbstractMetaBuilderPrivate::setArrayArgumentType(AbstractMetaFunction *func,
+ const FunctionModelItem &functionItem,
+ int i)
+{
+ if (i < 0 || i >= func->arguments().size()) {
+ qCWarning(lcShiboken).noquote()
+ << msgCannotSetArrayUsage(func->minimalSignature(), i,
+ QLatin1String("Index out of range."));
+ return false;
+ }
+ AbstractMetaType *metaType = func->arguments().at(i)->type();
+ if (metaType->indirections() == 0) {
+ qCWarning(lcShiboken).noquote()
+ << msgCannotSetArrayUsage(func->minimalSignature(), i,
+ QLatin1String("Type does not have indirections."));
+ return false;
+ }
+ TypeInfo elementType = functionItem->arguments().at(i)->type();
+ elementType.setIndirections(elementType.indirections() - 1);
+ bool ok;
+ AbstractMetaType *element = translateType(elementType, &ok);
+ if (element == nullptr || !ok) {
+ qCWarning(lcShiboken).noquote()
+ << msgCannotSetArrayUsage(func->minimalSignature(), i,
+ QLatin1String("Cannot translate element type ") + elementType.toString());
+ return false;
+ }
+ metaType->setArrayElementType(element);
+ metaType->setTypeUsagePattern(AbstractMetaType::NativePointerAsArrayPattern);
+ return true;
+}
+
AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModelItem functionItem)
{
if (!functionItem->templateParameters().isEmpty())
@@ -2322,7 +2358,16 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel
}
- fixArgumentNames(metaFunction);
+ if (!metaArguments.isEmpty()) {
+ const FunctionModificationList &mods = metaFunction->modifications(m_currentClass);
+ fixArgumentNames(metaFunction, mods);
+ for (const FunctionModification &mod : mods) {
+ for (const ArgumentModification &argMod : mod.argument_mods) {
+ if (argMod.array)
+ setArrayArgumentType(metaFunction, functionItem, argMod.index - 1);
+ }
+ }
+ }
// Determine class special functions
if (m_currentClass && metaFunction->arguments().size() == 1) {
@@ -2474,45 +2519,36 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ
return 0;
}
- // 2. Handle pointers specified as arrays with unspecified size
- bool arrayOfUnspecifiedSize = false;
if (typeInfo.arrays.size() > 0) {
- arrayOfUnspecifiedSize = true;
- for (int i = 0; i < typeInfo.arrays.size(); ++i)
- arrayOfUnspecifiedSize = arrayOfUnspecifiedSize && typeInfo.arrays.at(i).isEmpty();
-
- if (!arrayOfUnspecifiedSize) {
- TypeInfo newInfo;
- //newInfo.setArguments(typei.arguments());
- newInfo.setIndirections(typei.indirections());
- newInfo.setConstant(typei.isConstant());
- newInfo.setFunctionPointer(typei.isFunctionPointer());
- newInfo.setQualifiedName(typei.qualifiedName());
- newInfo.setReferenceType(typei.referenceType());
- newInfo.setVolatile(typei.isVolatile());
-
- AbstractMetaType* elementType = translateType(newInfo, ok);
- if (!(*ok))
- return 0;
+ TypeInfo newInfo;
+ //newInfo.setArguments(typei.arguments());
+ newInfo.setIndirections(typei.indirections());
+ newInfo.setConstant(typei.isConstant());
+ newInfo.setFunctionPointer(typei.isFunctionPointer());
+ newInfo.setQualifiedName(typei.qualifiedName());
+ newInfo.setReferenceType(typei.referenceType());
+ newInfo.setVolatile(typei.isVolatile());
+
+ AbstractMetaType* elementType = translateType(newInfo, ok);
+ if (!(*ok))
+ return 0;
- for (int i = typeInfo.arrays.size() - 1; i >= 0; --i) {
- QString s = typeInfo.arrays.at(i);
+ for (int i = typeInfo.arrays.size() - 1; i >= 0; --i) {
+ AbstractMetaType *arrayType = q->createMetaType();
+ arrayType->setArrayElementType(elementType);
+ if (!typeInfo.arrays.at(i).isEmpty()) {
bool _ok;
- int elems = findOutValueFromString(s, _ok);
-
- AbstractMetaType *arrayType = q->createMetaType();
- arrayType->setArrayElementCount(elems);
- arrayType->setArrayElementType(elementType);
- arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry() , elementType->typeEntry()->version()));
- decideUsagePattern(arrayType);
-
- elementType = arrayType;
+ const int elems = findOutValueFromString(typeInfo.arrays.at(i), _ok);
+ if (_ok)
+ arrayType->setArrayElementCount(elems);
}
+ arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry() , elementType->typeEntry()->version()));
+ decideUsagePattern(arrayType);
- return elementType;
- } else {
- typeInfo.indirections += typeInfo.arrays.size();
+ elementType = arrayType;
}
+
+ return elementType;
}
QStringList qualifierList = typeInfo.qualified_name;
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
index 8c4e4b185..71b69473e 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
@@ -155,7 +155,10 @@ public:
void sortLists();
AbstractMetaArgumentList reverseList(const AbstractMetaArgumentList &list);
void setInclude(TypeEntry *te, const QString &fileName) const;
- void fixArgumentNames(AbstractMetaFunction *func);
+ void fixArgumentNames(AbstractMetaFunction *func, const FunctionModificationList &mods);
+ bool setArrayArgumentType(AbstractMetaFunction *func,
+ const FunctionModelItem &functionItem, int i);
+
void fillAddedFunctions(AbstractMetaClass *metaClass);
AbstractMetaBuilder *q;
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
index 482efdaa0..d38eb8587 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
@@ -91,7 +91,7 @@ QDebug operator<<(QDebug d, const AbstractMetaVariable *av)
AbstractMetaType::AbstractMetaType()
:m_typeEntry(0),
- m_arrayElementCount(0),
+ m_arrayElementCount(-1),
m_arrayElementType(0),
m_originalTemplateType(0),
m_pattern(InvalidPattern),
@@ -147,6 +147,26 @@ AbstractMetaType *AbstractMetaType::copy() const
return cpy;
}
+AbstractMetaTypeCList AbstractMetaType::nestedArrayTypes() const
+{
+ AbstractMetaTypeCList result;
+ switch (m_pattern) {
+ case ArrayPattern:
+ for (const AbstractMetaType *t = this; t->typeUsagePattern() == ArrayPattern; ) {
+ const AbstractMetaType *elt = t->arrayElementType();
+ result.append(elt);
+ t = elt;
+ }
+ break;
+ case NativePointerAsArrayPattern:
+ result.append(m_arrayElementType);
+ break;
+ default:
+ break;
+ }
+ return result;
+}
+
QString AbstractMetaType::cppSignature() const
{
if (m_cachedCppSignature.isEmpty())
@@ -2545,13 +2565,32 @@ void AbstractMetaClass::fixFunctions()
setFunctions(funcs);
}
+static inline QString formatArraySize(int e)
+{
+ QString result;
+ result += QLatin1Char('[');
+ if (e >= 0)
+ result += QString::number(e);
+ result += QLatin1Char(']');
+ return result;
+}
QString AbstractMetaType::formatSignature(bool minimal) const
{
QString result;
if (isConstant())
result += QLatin1String("const ");
- result += typeEntry()->qualifiedCppName();
+ if (isArray()) {
+ // Build nested array dimensions a[2][3] in correct order
+ result += m_arrayElementType->minimalSignature();
+ const int arrayPos = result.indexOf(QLatin1Char('['));
+ if (arrayPos != -1)
+ result.insert(arrayPos, formatArraySize(m_arrayElementCount));
+ else
+ result.append(formatArraySize(m_arrayElementCount));
+ } else {
+ result += typeEntry()->qualifiedCppName();
+ }
if (!m_instantiations.isEmpty()) {
result += QLatin1Char('<');
if (minimal)
@@ -2586,6 +2625,11 @@ bool AbstractMetaType::hasNativeId() const
return (isQObject() || isValue() || isObject()) && typeEntry()->isNativeIdBased();
}
+bool AbstractMetaType::isCppPrimitive() const
+{
+ return m_pattern == PrimitivePattern && m_typeEntry->isCppPrimitive();
+}
+
bool AbstractMetaType::isTargetLangEnum() const
{
return isEnum() && !static_cast<const EnumTypeEntry *>(typeEntry())->forceInteger();
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h
index 921df4300..0529bed24 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h
@@ -326,6 +326,7 @@ public:
QObjectPattern,
ValuePointerPattern,
NativePointerPattern,
+ NativePointerAsArrayPattern, // "int*" as "int[]"
ContainerPattern,
SmartPointerPattern,
VariantPattern,
@@ -399,6 +400,8 @@ public:
return m_pattern == PrimitivePattern;
}
+ bool isCppPrimitive() const;
+
// returns true if the type is used as an enum
bool isEnum() const
{
@@ -558,6 +561,8 @@ public:
m_arrayElementType = t;
}
+ AbstractMetaTypeCList nestedArrayTypes() const;
+
QString cppSignature() const;
AbstractMetaType *copy() const;
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h b/sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h
index da8369895..6522ba2dd 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h
@@ -46,5 +46,6 @@ typedef QVector<AbstractMetaEnumValue *> AbstractMetaEnumValueList;
typedef QVector<AbstractMetaField *> AbstractMetaFieldList;
typedef QVector<AbstractMetaFunction *> AbstractMetaFunctionList;
typedef QVector<AbstractMetaType *> AbstractMetaTypeList;
+typedef QVector<const AbstractMetaType *> AbstractMetaTypeCList;
#endif // ABSTRACTMETALANG_TYPEDEFS_H
diff --git a/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp b/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp
index 4d46d44bc..408c51461 100644
--- a/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp
+++ b/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp
@@ -58,6 +58,45 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger()
QCOMPARE(arg->type()->arrayElementType()->name(), QLatin1String("double"));
}
+static QString functionMinimalSignature(const AbstractMetaClass *c, const QString &name)
+{
+ const AbstractMetaFunction *f = c->findFunction(name);
+ return f ? f->minimalSignature() : QString();
+}
+
+void TestArrayArgument::testArraySignature()
+{
+ const char cppCode[] ="\
+ struct A {\n\
+ void mi1(int arg[5]);\n\
+ void mi1c(const int arg[5]);\n\
+ void mi1cu(const int arg[]);\n\
+ void muc2(unsigned char *arg[2][3]);\n\
+ void mc2c(const char *arg[5][6]);\n\
+ };\n";
+ const char xmlCode[] = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='char'/>\n\
+ <primitive-type name='unsigned char'/>\n\
+ <primitive-type name='int'/>\n\
+ <object-type name='A'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
+ QVERIFY(!builder.isNull());
+ const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A"));
+ QCOMPARE(functionMinimalSignature(classA, QLatin1String("mi1")),
+ QLatin1String("mi1(int[5])"));
+ QCOMPARE(functionMinimalSignature(classA, QLatin1String("mi1c")),
+ QLatin1String("mi1c(const int[5])"));
+ QCOMPARE(functionMinimalSignature(classA, QLatin1String("mi1cu")),
+ QLatin1String("mi1cu(const int[])"));
+ QCOMPARE(functionMinimalSignature(classA, QLatin1String("muc2")),
+ QLatin1String("muc2(unsigned char*[2][3])"));
+ QCOMPARE(functionMinimalSignature(classA, QLatin1String("mc2c")),
+ QLatin1String("mc2c(const char*[5][6])"));
+}
+
void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue()
{
const char* cppCode ="\
diff --git a/sources/shiboken2/ApiExtractor/tests/testarrayargument.h b/sources/shiboken2/ApiExtractor/tests/testarrayargument.h
index b50232ef4..45ca8e655 100644
--- a/sources/shiboken2/ApiExtractor/tests/testarrayargument.h
+++ b/sources/shiboken2/ApiExtractor/tests/testarrayargument.h
@@ -35,6 +35,7 @@ class TestArrayArgument : public QObject
Q_OBJECT
private slots:
void testArrayArgumentWithSizeDefinedByInteger();
+ void testArraySignature();
void testArrayArgumentWithSizeDefinedByEnumValue();
void testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnum();
};
diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp
index 9adc5107b..13664c336 100644
--- a/sources/shiboken2/ApiExtractor/typesystem.cpp
+++ b/sources/shiboken2/ApiExtractor/typesystem.cpp
@@ -176,6 +176,7 @@ Handler::Handler(TypeDatabase* database, bool generate)
tagNames.insert(QLatin1String("no-null-pointer"), StackElement::NoNullPointers);
tagNames.insert(QLatin1String("reference-count"), StackElement::ReferenceCount);
tagNames.insert(QLatin1String("parent"), StackElement::ParentOwner);
+ tagNames.insert(QLatin1String("array"), StackElement::Array);
tagNames.insert(QLatin1String("inject-documentation"), StackElement::InjectDocumentation);
tagNames.insert(QLatin1String("modify-documentation"), StackElement::ModifyDocumentation);
tagNames.insert(QLatin1String("add-function"), StackElement::AddFunction);
@@ -1283,6 +1284,9 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
case StackElement::ParentOwner:
attributes.insert(QLatin1String("index"), QString());
attributes.insert(QLatin1String("action"), QString());
+ break;
+ case StackElement::Array:
+ break;
default:
{ };
};
@@ -1875,8 +1879,13 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts
m_contextStack.top()->functionMods.last().argument_mods.last().owner = ao;
}
break;
-
-
+ case StackElement::Array:
+ if (topElement.type != StackElement::ModifyArgument) {
+ m_error = QLatin1String("array must be child of modify-argument");
+ return false;
+ }
+ m_contextStack.top()->functionMods.last().argument_mods.last().array = true;
+ break;
case StackElement::InjectCode: {
if (!(topElement.type & StackElement::ComplexTypeEntryMask)
&& (topElement.type != StackElement::AddFunction)
diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h
index b75da48ba..6c65adbe1 100644
--- a/sources/shiboken2/ApiExtractor/typesystem.h
+++ b/sources/shiboken2/ApiExtractor/typesystem.h
@@ -211,16 +211,17 @@ public:
struct ArgumentModification
{
ArgumentModification() : removedDefaultExpression(false), removed(false),
- noNullPointers(false), index(-1), version(0) {}
+ noNullPointers(false), array(false), index(-1), version(0) {}
ArgumentModification(int idx, double vr)
: removedDefaultExpression(false), removed(false),
- noNullPointers(false), index(idx), version(vr) {}
+ noNullPointers(false), array(false), index(idx), version(vr) {}
// Should the default expression be removed?
uint removedDefaultExpression : 1;
uint removed : 1;
uint noNullPointers : 1;
uint resetAfterUse : 1;
+ uint array : 1; // consider "int*" to be "int[]"
// The index of this argument
int index;
diff --git a/sources/shiboken2/ApiExtractor/typesystem_p.h b/sources/shiboken2/ApiExtractor/typesystem_p.h
index f2105a631..d485aad42 100644
--- a/sources/shiboken2/ApiExtractor/typesystem_p.h
+++ b/sources/shiboken2/ApiExtractor/typesystem_p.h
@@ -107,6 +107,7 @@ class StackElement
NoNullPointers = 0x40000000,
ReferenceCount = 0x80000000,
ParentOwner = 0x90000000,
+ Array = 0xA0000000,
ArgumentModifiers = 0xff000000
};
diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp
index f60b195f2..a8e8735bb 100644
--- a/sources/shiboken2/generator/generator.cpp
+++ b/sources/shiboken2/generator/generator.cpp
@@ -515,9 +515,12 @@ bool Generator::isVoidPointer(const AbstractMetaType* type)
QString Generator::getFullTypeName(const TypeEntry* type) const
{
- return type->isCppPrimitive()
- ? type->qualifiedCppName()
- : (QLatin1String("::") + type->qualifiedCppName());
+ QString result = type->qualifiedCppName();
+ if (type->isArray())
+ type = static_cast<const ArrayTypeEntry *>(type)->nestedTypeEntry();
+ if (!type->isCppPrimitive())
+ result.prepend(QLatin1String("::"));
+ return result;
}
QString Generator::getFullTypeName(const AbstractMetaType* type) const
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index 91ed7eec5..f7c47fd05 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -2116,6 +2116,7 @@ static void checkTypeViability(const AbstractMetaFunction* func, const AbstractM
if (!type
|| !type->typeEntry()->isPrimitive()
|| type->indirections() == 0
+ || (type->indirections() == 1 && type->typeUsagePattern() == AbstractMetaType::NativePointerAsArrayPattern)
|| ShibokenGenerator::isCString(type)
|| func->argumentRemoved(argIdx)
|| !func->typeReplaced(argIdx).isEmpty()
@@ -2206,6 +2207,23 @@ const AbstractMetaType* CppGenerator::getArgumentType(const AbstractMetaFunction
return argType;
}
+static inline QString arrayHandleType(const AbstractMetaTypeCList &nestedArrayTypes)
+{
+ switch (nestedArrayTypes.size()) {
+ case 1:
+ return QStringLiteral("Shiboken::Conversions::ArrayHandle<")
+ + nestedArrayTypes.constLast()->minimalSignature()
+ + QLatin1Char('>');
+ case 2:
+ return QStringLiteral("Shiboken::Conversions::Array2Handle<")
+ + nestedArrayTypes.constLast()->minimalSignature()
+ + QStringLiteral(", ")
+ + QString::number(nestedArrayTypes.constFirst()->arrayElementCount())
+ + QLatin1Char('>');
+ }
+ return QString();
+}
+
void CppGenerator::writePythonToCppTypeConversion(QTextStream& s,
const AbstractMetaType* type,
const QString& pyIn,
@@ -2227,7 +2245,13 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream& s,
&& !isCppPrimitive(type)
&& isNotContainerEnumOrFlags
&& !(treatAsPointer || isPointerOrObjectType);
- QString typeName = getFullTypeNameWithoutModifiers(type);
+
+ const AbstractMetaTypeCList nestedArrayTypes = type->nestedArrayTypes();
+ const bool isCppPrimitiveArray = !nestedArrayTypes.isEmpty()
+ && nestedArrayTypes.constLast()->isCppPrimitive();
+ QString typeName = isCppPrimitiveArray
+ ? arrayHandleType(nestedArrayTypes)
+ : getFullTypeNameWithoutModifiers(type);
bool isProtectedEnum = false;
@@ -2244,7 +2268,9 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream& s,
}
s << INDENT << typeName;
- if (treatAsPointer || isPointerOrObjectType) {
+ if (isCppPrimitiveArray) {
+ s << ' ' << cppOut;
+ } else if (treatAsPointer || isPointerOrObjectType) {
s << "* " << cppOut;
if (!defaultValue.isEmpty())
s << " = " << defaultValue;
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
index 2693ecf40..b6242c57f 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -779,6 +779,13 @@ QString ShibokenGenerator::converterObject(const AbstractMetaType* type)
return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter<const char*>()");
if (isVoidPointer(type))
return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter<void*>()");
+ const AbstractMetaTypeCList nestedArrayTypes = type->nestedArrayTypes();
+ if (!nestedArrayTypes.isEmpty() && nestedArrayTypes.constLast()->isCppPrimitive()) {
+ return QStringLiteral("Shiboken::Conversions::ArrayTypeConverter<")
+ + nestedArrayTypes.constLast()->minimalSignature()
+ + QLatin1String(">(") + QString::number(nestedArrayTypes.size())
+ + QLatin1Char(')');
+ }
if (type->typeEntry()->isContainer()) {
return convertersVariableName(type->typeEntry()->targetLangPackage())
+ QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']');
@@ -1232,8 +1239,8 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType*
return customCheck;
}
+ QString result = QLatin1String("Shiboken::Conversions::");
if (isWrapperType(metaType)) {
- QString result = QLatin1String("Shiboken::Conversions::");
if (isPointer(metaType) || isValueTypeWithCopyConstructorOnly(metaType))
result += QLatin1String("isPythonToCppPointerConvertible");
else if (metaType->referenceType() == LValueReference)
@@ -1244,8 +1251,18 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType*
+ cpythonTypeNameExt(metaType) + QLatin1String("), ");
return result;
}
- return QStringLiteral("Shiboken::Conversions::isPythonToCppConvertible(%1, ")
- .arg(converterObject(metaType));
+ result += QLatin1String("isPythonToCppConvertible(") + converterObject(metaType);
+ // Write out array sizes if known
+ const AbstractMetaTypeCList nestedArrayTypes = metaType->nestedArrayTypes();
+ if (!nestedArrayTypes.isEmpty() && nestedArrayTypes.constLast()->isCppPrimitive()) {
+ const int dim1 = metaType->arrayElementCount();
+ const int dim2 = nestedArrayTypes.constFirst()->isArray()
+ ? nestedArrayTypes.constFirst()->arrayElementCount() : -1;
+ result += QLatin1String(", ") + QString::number(dim1)
+ + QLatin1String(", ") + QString::number(dim2);
+ }
+ result += QLatin1String(", ");
+ return result;
}
QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaArgument *metaArg, bool genericNumberType)
@@ -1330,8 +1347,12 @@ QString ShibokenGenerator::argumentString(const AbstractMetaFunction *func,
arg = modified_type.replace(QLatin1Char('$'), QLatin1Char('.'));
if (!(options & Generator::SkipName)) {
- arg += QLatin1Char(' ');
- arg += argument->name();
+ // "int a", "int a[]"
+ const int arrayPos = arg.indexOf(QLatin1Char('['));
+ if (arrayPos != -1)
+ arg.insert(arrayPos, QLatin1Char(' ') + argument->name());
+ else
+ arg.append(QLatin1Char(' ') + argument->name());
}
if ((options & Generator::SkipDefaultValues) != Generator::SkipDefaultValues &&
diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt
index 5363ccf42..06d6330f5 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}")
@@ -21,6 +38,7 @@ basewrapper.cpp
debugfreehook.cpp
gilstate.cpp
helper.cpp
+sbkarrayconverter.cpp
sbkconverter.cpp
sbkenum.cpp
sbkmodule.cpp
@@ -31,9 +49,19 @@ typeresolver.cpp
shibokenbuffer.cpp
)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_CURRENT_BINARY_DIR}
- ${SBK_PYTHON_INCLUDE_DIR})
+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}"
@@ -48,6 +76,7 @@ install(FILES
conversions.h
gilstate.h
helper.h
+ sbkarrayconverter.h
sbkconverter.h
sbkenum.h
sbkmodule.h
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 2a51edd76..b86e09fa2 100644
--- a/sources/shiboken2/libshiboken/sbkconverter.cpp
+++ b/sources/shiboken2/libshiboken/sbkconverter.cpp
@@ -39,6 +39,7 @@
#include "sbkconverter.h"
#include "sbkconverter_p.h"
+#include "sbkarrayconverter_p.h"
#include "basewrapper_p.h"
#include "autodecref.h"
#include "sbkdbg.h"
@@ -54,6 +55,8 @@ static ConvertersMap converters;
namespace Shiboken {
namespace Conversions {
+void initArrayConverters();
+
void init()
{
static SbkConverter* primitiveTypeConverters[] = {
@@ -95,9 +98,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,
@@ -254,6 +259,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 7489b930d..18b6bbcf3 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 b38561780..fd1f7b6b2 100644
--- a/sources/shiboken2/libshiboken/sbkconverter_p.h
+++ b/sources/shiboken2/libshiboken/sbkconverter_p.h
@@ -571,4 +571,14 @@ struct Primitive<void*> : OnePrimitive<void*>
}
};
+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/sbknumpyarrayconverter.cpp b/sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp
new file mode 100644
index 000000000..e941fbe26
--- /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) {
+ PyErr_Print();
+ PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import");
+ 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 2738bf51f..5bdef1b86 100644
--- a/sources/shiboken2/libshiboken/shiboken.h
+++ b/sources/shiboken2/libshiboken/shiboken.h
@@ -48,6 +48,7 @@
#include "gilstate.h"
#include "threadstatesaver.h"
#include "helper.h"
+#include "sbkarrayconverter.h"
#include "sbkconverter.h"
#include "sbkenum.h"
#include "sbkmodule.h"
diff --git a/sources/shiboken2/tests/libsample/functions.cpp b/sources/shiboken2/tests/libsample/functions.cpp
index 4a15cdae8..bf73d5ed7 100644
--- a/sources/shiboken2/tests/libsample/functions.cpp
+++ b/sources/shiboken2/tests/libsample/functions.cpp
@@ -28,7 +28,9 @@
#include "functions.h"
#include <string.h>
+#include <algorithm>
#include <iostream>
+#include <numeric>
using namespace std;
@@ -197,6 +199,45 @@ acceptOddBoolReference(OddBool& x)
return x;
}
+int sumIntArray(int array[4])
+{
+ return std::accumulate(array, array + 4, 0);
+}
+
+double sumDoubleArray(double array[4])
+{
+ return std::accumulate(array, array + 4, double(0));
+}
+
+int sumIntMatrix(int m[2][3])
+{
+ int result = 0;
+ for (int r = 0; r < 2; ++r) {
+ for (int c = 0; c < 3; ++c)
+ result += m[r][c];
+ }
+ return result;
+}
+
+double sumDoubleMatrix(double m[2][3])
+{
+ double result = 0;
+ for (int r = 0; r < 2; ++r) {
+ for (int c = 0; c < 3; ++c)
+ result += m[r][c];
+ }
+ return result;
+}
+
+ArrayModifyTest::ArrayModifyTest()
+{
+}
+
+int ArrayModifyTest::sumIntArray(int n, int *array)
+{
+ return std::accumulate(array, array + n, 0);
+}
+
ClassWithFunctionPointer::ClassWithFunctionPointer()
{
callFunctionPointer(0, &ClassWithFunctionPointer::doNothing);
diff --git a/sources/shiboken2/tests/libsample/functions.h b/sources/shiboken2/tests/libsample/functions.h
index 89a175bc4..a53f97c6e 100644
--- a/sources/shiboken2/tests/libsample/functions.h
+++ b/sources/shiboken2/tests/libsample/functions.h
@@ -81,6 +81,17 @@ LIBSAMPLE_API double acceptDouble(double x);
LIBSAMPLE_API int acceptIntReference(int& x);
LIBSAMPLE_API OddBool acceptOddBoolReference(OddBool& x);
+LIBSAMPLE_API int sumIntArray(int array[4]);
+LIBSAMPLE_API double sumDoubleArray(double array[4]);
+LIBSAMPLE_API int sumIntMatrix(int m[2][3]);
+LIBSAMPLE_API double sumDoubleMatrix(double m[2][3]);
+
+class LIBSAMPLE_API ArrayModifyTest
+{
+public:
+ ArrayModifyTest();
+ int sumIntArray(int n, int *array);
+};
class LIBSAMPLE_API ClassWithFunctionPointer
{
diff --git a/sources/shiboken2/tests/samplebinding/CMakeLists.txt b/sources/shiboken2/tests/samplebinding/CMakeLists.txt
index 1b97bd0e8..b3c9df0dd 100644
--- a/sources/shiboken2/tests/samplebinding/CMakeLists.txt
+++ b/sources/shiboken2/tests/samplebinding/CMakeLists.txt
@@ -7,6 +7,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/typesystem_sample.xml
set(sample_SRC
${CMAKE_CURRENT_BINARY_DIR}/sample/abstractmodifications_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/abstract_wrapper.cpp
+${CMAKE_CURRENT_BINARY_DIR}/sample/arraymodifytest_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/base1_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/base2_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/sample/base3_wrapper.cpp
diff --git a/sources/shiboken2/tests/samplebinding/array_numpy_test.py b/sources/shiboken2/tests/samplebinding/array_numpy_test.py
new file mode 100644
index 000000000..bde46f2e3
--- /dev/null
+++ b/sources/shiboken2/tests/samplebinding/array_numpy_test.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of PySide2.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## 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 General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## 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-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+'''Test case for NumPy Array types.'''
+
+import unittest
+import sample
+
+hasNumPy = False
+
+try:
+ import numpy
+ hasNumPy = True
+except ImportError:
+ pass
+
+class ArrayTester(unittest.TestCase):
+ '''Test case for NumPy arrays.'''
+
+ def testIntArray(self):
+ intList = numpy.array([1, 2, 3, 4], dtype = 'int32')
+ self.assertEqual(sample.sumIntArray(intList), 10)
+
+ def testDoubleArray(self):
+ doubleList = numpy.array([1, 2, 3, 4], dtype = 'double')
+ self.assertEqual(sample.sumDoubleArray(doubleList), 10)
+
+ def testIntMatrix(self):
+ intMatrix = numpy.array([[1, 2, 3], [4, 5, 6]], dtype = 'int32')
+ self.assertEqual(sample.sumIntMatrix(intMatrix), 21)
+
+ def testDoubleMatrix(self):
+ doubleMatrix = numpy.array([[1, 2, 3], [4, 5, 6]], dtype = 'double')
+ self.assertEqual(sample.sumDoubleMatrix(doubleMatrix), 21)
+
+if __name__ == '__main__' and hasNumPy:
+ unittest.main()
diff --git a/sources/shiboken2/tests/samplebinding/array_sequence_test.py b/sources/shiboken2/tests/samplebinding/array_sequence_test.py
new file mode 100644
index 000000000..0fd2ec636
--- /dev/null
+++ b/sources/shiboken2/tests/samplebinding/array_sequence_test.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of PySide2.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## 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 General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## 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-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+'''Test case for Array types (PySequence).'''
+
+import unittest
+import sample
+
+class ArrayTester(unittest.TestCase):
+ '''Test case for arrays.'''
+
+ def testIntArray(self):
+ intList = [1, 2, 3, 4]
+ self.assertEqual(sample.sumIntArray(intList), 10)
+
+ def testIntArrayModified(self):
+ intList = [1, 2, 3, 4]
+ tester = sample.ArrayModifyTest()
+ self.assertEqual(tester.sumIntArray(4, intList), 10)
+
+ def testDoubleArray(self):
+ doubleList = [1.2, 2.3, 3.4, 4.5]
+ self.assertEqual(sample.sumDoubleArray(doubleList), 11.4)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml
index 089f835fc..efc4205ae 100644
--- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml
+++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml
@@ -501,11 +501,21 @@
<function signature="gimmeInt()" />
<function signature="gimmeDouble()" />
<function signature="makeCString()" />
+ <function signature="sumIntArray(int[4])"/>
+ <function signature="sumDoubleArray(double[4])"/>
+ <function signature="sumIntMatrix(int[2][3])"/>
+ <function signature="sumDoubleMatrix(double[2][3])"/>
<function signature="multiplyPair(std::pair&lt;double, double>)" />
<function signature="returnCString()" />
<function signature="overloadedFunc(double)" />
<function signature="overloadedFunc(int)" />
+ <value-type name="ArrayModifyTest">
+ <modify-function signature="sumIntArray(int, int*)">
+ <modify-argument index="2"><array/></modify-argument>
+ </modify-function>
+ </value-type>
+
<value-type name="ClassWithFunctionPointer">
<suppress-warning text="skipping function 'ClassWithFunctionPointer::callFunctionPointer', unmatched parameter type 'void (*)(void*)'" />
</value-type>
@@ -1159,7 +1169,7 @@
<!-- change the name of this virtual method -->
<modify-function signature="className()" rename="name"/>
- <modify-function signature="sumPointArray(int, const Point*)">
+ <modify-function signature="sumPointArray(int, const Point[])">
<modify-argument index="1">
<remove-argument/>
<conversion-rule class="native">
@@ -1950,7 +1960,7 @@
<define-ownership owner="c++"/>
</modify-argument>
</modify-function>
- <modify-function signature="acceptSequence(const char**)">
+ <modify-function signature="acceptSequence(const char*[])">
<modify-argument index="1">
<replace-type modified-type="PySequence" />
<conversion-rule class="native">