aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2023-01-10 15:14:13 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2023-01-11 15:28:28 +0100
commit4c2c58511df05febd7f51fe41c8e377435f9271e (patch)
tree046fc150014aad7f34372e18544d9a05bbcfbfea
parent2f0061786046f0855373eb4e099a8bfe0e7b7c2a (diff)
shiboken6/libminimal: Add std::array (C++ 11)
[ChangeLog][shiboken6] Support for std::array has been added. Task-number: PYSIDE-1605 Task-number: PYSIDE-2174 Change-Id: I5192dfe1fa88d794856169638bb97abfc916bcf5 Reviewed-by: Christian Tismer <tismer@stackless.com>
-rw-r--r--sources/shiboken6/ApiExtractor/predefined_templates.cpp19
-rw-r--r--sources/shiboken6/ApiExtractor/typedatabase.cpp8
-rw-r--r--sources/shiboken6/doc/typesystem_specifying_types.rst11
-rw-r--r--sources/shiboken6/doc/typesystem_templates.rst2
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator_container.cpp30
-rw-r--r--sources/shiboken6/tests/libminimal/containeruser.cpp22
-rw-r--r--sources/shiboken6/tests/libminimal/containeruser.h8
-rw-r--r--sources/shiboken6/tests/minimalbinding/containeruser_test.py11
-rw-r--r--sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml7
9 files changed, 102 insertions, 16 deletions
diff --git a/sources/shiboken6/ApiExtractor/predefined_templates.cpp b/sources/shiboken6/ApiExtractor/predefined_templates.cpp
index 6e1459940..84c8fb5bc 100644
--- a/sources/shiboken6/ApiExtractor/predefined_templates.cpp
+++ b/sources/shiboken6/ApiExtractor/predefined_templates.cpp
@@ -39,6 +39,23 @@ while (true) {
return result;
}
+// Convert a sequence to a limited/fixed array
+static QString pySequenceToCppArray()
+{
+ return uR"(Shiboken::AutoDecRef it(PyObject_GetIter(%in));
+for (auto oit = std::begin(%out), oend = std::end(%out); oit != oend; ++oit) {
+ Shiboken::AutoDecRef pyItem(PyIter_Next(it.object()));
+ if (pyItem.isNull()) {
+ if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration))
+ PyErr_Clear();
+ break;
+ }
+ %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem);
+ *oit = cppItem;
+}
+)"_s;
+}
+
static const char stlMapKeyAccessor[] = "->first";
static const char stlMapValueAccessor[] = "->second";
static const char qtMapKeyAccessor[] = ".key()";
@@ -192,6 +209,8 @@ return %out;)"_s},
pySequenceToCppContainer(u"push_back"_s, false)},
{u"shiboken_conversion_pyiterable_to_cppsequentialcontainer_reserve"_s,
pySequenceToCppContainer(u"push_back"_s, true)},
+ {u"shiboken_conversion_pyiterable_to_cpparray"_s,
+ pySequenceToCppArray()},
{u"shiboken_conversion_pyiterable_to_cppsetcontainer"_s,
pySequenceToCppContainer(u"insert"_s, false)},
diff --git a/sources/shiboken6/ApiExtractor/typedatabase.cpp b/sources/shiboken6/ApiExtractor/typedatabase.cpp
index 1b2d7e7b7..240ad0df8 100644
--- a/sources/shiboken6/ApiExtractor/typedatabase.cpp
+++ b/sources/shiboken6/ApiExtractor/typedatabase.cpp
@@ -856,6 +856,7 @@ void TypeDatabasePrivate::addBuiltInContainerTypes(const TypeDatabaseParserConte
{
// Unless the user has added the standard containers (potentially with
// some opaque types), add them by default.
+ const bool hasStdArray = findType(u"std::array"_s) != nullptr;
const bool hasStdPair = findType(u"std::pair"_s) != nullptr;
const bool hasStdList = findType(u"std::list"_s) != nullptr;
const bool hasStdVector = findType(u"std::vector"_s) != nullptr;
@@ -866,6 +867,13 @@ void TypeDatabasePrivate::addBuiltInContainerTypes(const TypeDatabaseParserConte
return;
QByteArray ts = R"(<?xml version="1.0" encoding="UTF-8"?><typesystem>)";
+ if (!hasStdArray) {
+ ts += containerTypeSystemSnippet(
+ "std::array", "list", "array",
+ "shiboken_conversion_cppsequence_to_pylist",
+ "PySequence",
+ "shiboken_conversion_pyiterable_to_cpparray");
+ }
if (!hasStdPair) {
ts += containerTypeSystemSnippet(
"std::pair", "pair", "utility",
diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst
index 52b0ee4df..dca076c1a 100644
--- a/sources/shiboken6/doc/typesystem_specifying_types.rst
+++ b/sources/shiboken6/doc/typesystem_specifying_types.rst
@@ -541,8 +541,15 @@ container-type
are equivalent to *map* and *multi-map*, respectively.
The *optional* **opaque-containers** attribute specifies a semi-colon separated
- list of colon separated pairs of instantiation and name for
- :ref:`opaque-containers`.
+ list of mappings from instantiations to a type name for
+ :ref:`opaque-containers`:
+
+ .. code-block:: xml
+
+ <typesystem>
+ <container-type name="std::array"
+ opaque-containers ="int,3:IntArray3;float,4:FloatArray4">
+
The *optional* **since** value is used to specify the API version of this container.
diff --git a/sources/shiboken6/doc/typesystem_templates.rst b/sources/shiboken6/doc/typesystem_templates.rst
index abb7ab3f2..bf9598db1 100644
--- a/sources/shiboken6/doc/typesystem_templates.rst
+++ b/sources/shiboken6/doc/typesystem_templates.rst
@@ -89,6 +89,8 @@ In case they need to explicitly specified, the following templates can be used:
+----------------------------------------------------------------------+------------------------------------------------------------------------------------+
| ``shiboken_conversion_pyiterable_to_cppsequentialcontainer_reserve`` | Convert an iterable Python type to a C++ sequential container supporting reserve() |
+----------------------------------------------------------------------+------------------------------------------------------------------------------------+
+ | ``shiboken_conversion_pyiterable_to_cpparray`` | Convert an iterable Python type to a fixed-size array (std::array, std::span) |
+ +----------------------------------------------------------------------+------------------------------------------------------------------------------------+
| ``shiboken_conversion_pyiterable_to_cppsetcontainer`` | Convert a PySequence to a set-type C++ container (std::set/QSet) |
+----------------------------------------------------------------------+------------------------------------------------------------------------------------+
| ``shiboken_conversion_stdmap_to_pydict`` | Convert a std::map/std::unordered_map to a PyDict |
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp b/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
index 5c691df6f..360ae703d 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator_container.cpp
@@ -151,22 +151,26 @@ CppGenerator::OpaqueContainerData
+ cppSignature + u'>';
// methods
- const bool isStdVector = containerType.name() == u"std::vector";
+ const QString &containerName = containerType.name();
+ const bool isStdVector = containerName == u"std::vector";
+ const bool isFixed = containerName == u"std::array";
const QString methods = result.name + u"_methods"_s;
s << "static PyMethodDef " << methods << "[] = {\n" << indent;
- writeMethod(s, privateObjType, "push_back");
- writeMethod(s, privateObjType, "push_back", "append"); // Qt convention
- writeNoArgsMethod(s, privateObjType, "clear");
- writeNoArgsMethod(s, privateObjType, "pop_back");
- writeNoArgsMethod(s, privateObjType, "pop_back", "removeLast"); // Qt convention
- if (!isStdVector) {
- writeMethod(s, privateObjType, "push_front");
- writeMethod(s, privateObjType, "push_front", "prepend"); // Qt convention
- writeNoArgsMethod(s, privateObjType, "pop_front");
- writeMethod(s, privateObjType, "pop_front", "removeFirst"); // Qt convention
+ if (!isFixed) {
+ writeMethod(s, privateObjType, "push_back");
+ writeMethod(s, privateObjType, "push_back", "append"); // Qt convention
+ writeNoArgsMethod(s, privateObjType, "clear");
+ writeNoArgsMethod(s, privateObjType, "pop_back");
+ writeNoArgsMethod(s, privateObjType, "pop_back", "removeLast"); // Qt convention
+ if (!isStdVector) {
+ writeMethod(s, privateObjType, "push_front");
+ writeMethod(s, privateObjType, "push_front", "prepend"); // Qt convention
+ writeNoArgsMethod(s, privateObjType, "pop_front");
+ writeMethod(s, privateObjType, "pop_front", "removeFirst"); // Qt convention
+ }
+ writeMethod(s, privateObjType, "reserve"); // SFINAE'd out for list
+ writeNoArgsMethod(s, privateObjType, "capacity");
}
- writeMethod(s, privateObjType, "reserve");
- writeNoArgsMethod(s, privateObjType, "capacity");
writeNoArgsMethod(s, privateObjType, "data");
writeNoArgsMethod(s, privateObjType, "constData");
s << "{nullptr, nullptr, 0, nullptr} // Sentinel\n"
diff --git a/sources/shiboken6/tests/libminimal/containeruser.cpp b/sources/shiboken6/tests/libminimal/containeruser.cpp
index 78fc7a045..29af52aef 100644
--- a/sources/shiboken6/tests/libminimal/containeruser.cpp
+++ b/sources/shiboken6/tests/libminimal/containeruser.cpp
@@ -6,7 +6,7 @@
#include <algorithm>
#include <numeric>
-ContainerUser::ContainerUser() : m_intVector{1, 2, 3}
+ContainerUser::ContainerUser() : m_intVector{1, 2, 3}, m_intArray{1, 2, 3}
{
}
@@ -33,3 +33,23 @@ void ContainerUser::setIntVector(const std::vector<int> &v)
{
m_intVector = v;
}
+
+std::array<int, 3> ContainerUser::createIntArray()
+{
+ return {1, 2, 3};
+}
+
+int ContainerUser::sumIntArray(const std::array<int, 3> &intArray)
+{
+ return std::accumulate(intArray.cbegin(), intArray.cend(), 0);
+}
+
+std::array<int, 3> &ContainerUser::intArray()
+{
+ return m_intArray;
+}
+
+void ContainerUser::setIntArray(const std::array<int, 3> &a)
+{
+ m_intArray = a;
+}
diff --git a/sources/shiboken6/tests/libminimal/containeruser.h b/sources/shiboken6/tests/libminimal/containeruser.h
index 4cb4df0b9..55e4020ec 100644
--- a/sources/shiboken6/tests/libminimal/containeruser.h
+++ b/sources/shiboken6/tests/libminimal/containeruser.h
@@ -6,6 +6,7 @@
#include "libminimalmacros.h"
+#include <array>
#include <vector>
/// Exercise simple, sequential containers. More advanced tests are in ListUser
@@ -21,8 +22,15 @@ public:
std::vector<int> &intVector();
void setIntVector(const std::vector<int> &);
+ static std::array<int, 3> createIntArray();
+ static int sumIntArray(const std::array<int, 3> &intArray);
+
+ std::array<int, 3> &intArray();
+ void setIntArray(const std::array<int, 3> &);
+
private:
std::vector<int> m_intVector;
+ std::array<int, 3> m_intArray;
};
#endif // CONTAINERUSER_H
diff --git a/sources/shiboken6/tests/minimalbinding/containeruser_test.py b/sources/shiboken6/tests/minimalbinding/containeruser_test.py
index b08989d2f..25d683957 100644
--- a/sources/shiboken6/tests/minimalbinding/containeruser_test.py
+++ b/sources/shiboken6/tests/minimalbinding/containeruser_test.py
@@ -28,6 +28,17 @@ class ContainerTest(unittest.TestCase):
oc[0] = 42
self.assertEqual(cu.intVector()[0], 42)
+ def testArrayConversion(self):
+ v = ContainerUser.createIntArray()
+ self.assertEqual(ContainerUser.sumIntArray(v), 6)
+
+ def testArrayOpaqueContainer(self):
+ cu = ContainerUser()
+ oc = cu.intArray()
+ self.assertEqual(oc[0], 1)
+ oc[0] = 42
+ self.assertEqual(cu.intArray()[0], 42)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml b/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml
index 1b16e0709..e73ddc228 100644
--- a/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml
+++ b/sources/shiboken6/tests/minimalbinding/typesystem_minimal.xml
@@ -19,6 +19,8 @@
<opaque-container name="std::vector" opaque-containers="int:StdIntVector"/>
+ <opaque-container name="std::array" opaque-containers="int,3:StdIntArray"/>
+
<object-type name="Obj"/>
<value-type name="Val">
<enum-type name="ValEnum"/>
@@ -44,6 +46,11 @@
<replace-type modified-type="StdIntVector"/>
</modify-argument>
</modify-function>
+ <modify-function signature="intArray()">
+ <modify-argument index="return">
+ <replace-type modified-type="StdIntArray"/>
+ </modify-argument>
+ </modify-function>
</value-type>
<!-- Test wrapping of a typedef -->