From eb6576c6afdbd41e4f053154b081c68f6ceef080 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 3 Sep 2019 17:43:33 +0200 Subject: [PATCH] python: sad workaround for a nasty problem deep inside pybind. :( --- src/python/magnum/magnum.cpp | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/python/magnum/magnum.cpp b/src/python/magnum/magnum.cpp index 06de0f9..5aade8f 100644 --- a/src/python/magnum/magnum.cpp +++ b/src/python/magnum/magnum.cpp @@ -67,19 +67,40 @@ template void imageView(py::class_>& c) { */ c - /* Constructors */ - .def(py::init([](const PixelStorage& storage, PixelFormat format, const typename PyDimensionTraits::VectorType& size, const Containers::ArrayView& data) { - return pyImageViewHolder(T{storage, format, size, data}, pyObjectHolderFor(data).owner); - }), "Constructor") - .def(py::init([](PixelFormat format, const typename PyDimensionTraits::VectorType& size, const Containers::ArrayView& data) { - return pyImageViewHolder(T{format, size, data}, pyObjectHolderFor(data).owner); - }), "Constructor") + /* Constructors. The variants *not* taking an array view have to be + first, otherwise things fail on systems that don't have numpy + installed: + + =================================================================== + ERROR: test_init_empty (test.test.ImageView) + ------------------------------------------------------------------- + Traceback (most recent call last): + File ".../magnum/test/test.py", line 102, in test_init_empty + b = ImageView2D(storage, PixelFormat.R32F, (8, 8)) + ModuleNotFoundError: No module named 'numpy' + + This is because of the order in which pybind processes arguments --- + it would first try to match the (PixelFormat, Vector2i, ArrayView) + variant and *somehow* getting all the way to the third argument, + where, because ArrayView is marked as implicitly convertible from + py::array for numpy compatibility, it ends up doing this in numpy.h: + + module m = module::import("numpy.core.multiarray"); + auto c = m.attr("_ARRAY_API"); + + Wonderful, isn't it. */ .def(py::init([](const PixelStorage& storage, PixelFormat format, const typename PyDimensionTraits::VectorType& size) { return T{storage, format, size}; }), "Construct an empty view") .def(py::init([](PixelFormat format, const typename PyDimensionTraits::VectorType& size) { return T{format, size}; }), "Construct an empty view") + .def(py::init([](const PixelStorage& storage, PixelFormat format, const typename PyDimensionTraits::VectorType& size, const Containers::ArrayView& data) { + return pyImageViewHolder(T{storage, format, size, data}, pyObjectHolderFor(data).owner); + }), "Constructor") + .def(py::init([](PixelFormat format, const typename PyDimensionTraits::VectorType& size, const Containers::ArrayView& data) { + return pyImageViewHolder(T{format, size, data}, pyObjectHolderFor(data).owner); + }), "Constructor") /* Properties */ .def_property_readonly("storage", &T::storage, "Storage of pixel data")