diff --git a/src/python/corrade/test/test_containers.py b/src/python/corrade/test/test_containers.py index b5e9ff8..f32a6bb 100644 --- a/src/python/corrade/test/test_containers.py +++ b/src/python/corrade/test/test_containers.py @@ -1096,6 +1096,15 @@ class StridedArrayViewCustomType(unittest.TestCase): av[1] = 11111 self.assertEqual(a.list, [0, -7656581, 0, -333, 11111, 4666]) + # It should also be possible to take a custom-typed view as an argument + b = test_stridedarrayview.MutableContaineri() + b.copy_from(memoryview(a.view)) + self.assertEqual(b.list, [0, -7656581, 0, -333, 11111, 4666]) + + # But only if the type actually matches + with self.assertRaisesRegex(BufferError, "expected a view of format i but got Qf"): + b.copy_from(memoryview(test_stridedarrayview.MutableContainerlf().view)) + # mutable_vector3d and mutable_long_float tested in test_containers_numpy # as memoryview can't handle their types diff --git a/src/python/corrade/test/test_stridedarrayview.cpp b/src/python/corrade/test/test_stridedarrayview.cpp index ef525b5..c6f901c 100644 --- a/src/python/corrade/test/test_stridedarrayview.cpp +++ b/src/python/corrade/test/test_stridedarrayview.cpp @@ -51,6 +51,14 @@ template struct Container { return {Containers::arrayView(data), {2, 3}}; } + void copyFrom(const Containers::StridedArrayView2D& view) { + for(std::size_t i = 0, iMax = Utility::min(view.size()[0], std::size_t{2}); i != iMax; ++i) { + for(std::size_t j = 0, jMax = Utility::min(view.size()[1], std::size_t{3}); j != jMax; ++j) { + data[i*3 + j] = view[i][j]; + } + } + } + std::vector::type> list() const { return {data, data + 6}; } @@ -77,6 +85,16 @@ template void container(py::class_>& c) { }) .def_property_readonly("list", &Container::list); } +template void mutableContainer(py::class_>& c) { + c + .def("copy_from", [](Container& self, const Containers::PyStridedArrayView<2, const char>& view) { + if(view.format != Corrade::Containers::Implementation::pythonFormatString()) { + PyErr_Format(PyExc_BufferError, "expected a view of format %s but got %s", Corrade::Containers::Implementation::pythonFormatString(), view.format.data()); + throw py::error_already_set{}; + } + self.copyFrom(Containers::arrayCast(view)); + }); +} /* TODO: remove declaration when https://github.com/pybind/pybind11/pull/1863 is released */ @@ -90,8 +108,11 @@ PYBIND11_MODULE(test_stridedarrayview, m) { py::class_>> mutableContainerlf{m, "MutableContainerlf"}; container(containers); container(mutableContaineri); + mutableContainer(mutableContaineri); container(mutableContainer3d); + mutableContainer(mutableContainer3d); container(mutableContainerlf); + mutableContainer(mutableContainerlf); py::class_{m, "MutableContainerDynamicType"} .def(py::init())