diff --git a/example/example-numpy-dtypes.cpp b/example/example-numpy-dtypes.cpp index b5c0b0655..d77945b1a 100644 --- a/example/example-numpy-dtypes.cpp +++ b/example/example-numpy-dtypes.cpp @@ -178,24 +178,47 @@ py::array_t test_array_ctors(int i) { auto dtype = py::dtype("int32"); py::buffer_info buf_ndim1(vptr, 4, "i", 6); + py::buffer_info buf_ndim1_null(nullptr, 4, "i", 6); py::buffer_info buf_ndim2(vptr, 4, "i", 2, shape, strides); + py::buffer_info buf_ndim2_null(nullptr, 4, "i", 2, shape, strides); + + auto fill = [](py::array arr) { + auto req = arr.request(); + for (int i = 0; i < 6; i++) ((int32_t *) req.ptr)[i] = i + 1; + return arr; + }; switch (i) { // shape: (3, 2) - case 0: return arr_t(shape, ptr, strides); - case 1: return py::array(shape, ptr, strides); - case 2: return py::array(dtype, shape, vptr, strides); - case 3: return arr_t(shape, ptr); - case 4: return py::array(shape, ptr); - case 5: return py::array(dtype, shape, vptr); - case 6: return arr_t(buf_ndim2); - case 7: return py::array(buf_ndim2); + case 10: return arr_t(shape, strides, ptr); + case 11: return py::array(shape, strides, ptr); + case 12: return py::array(dtype, shape, strides, vptr); + case 13: return arr_t(shape, ptr); + case 14: return py::array(shape, ptr); + case 15: return py::array(dtype, shape, vptr); + case 16: return arr_t(buf_ndim2); + case 17: return py::array(buf_ndim2); + // shape: (3, 2) - post-fill + case 20: return fill(arr_t(shape, strides)); + case 21: return py::array(shape, strides, ptr); // can't have nullptr due to templated ctor + case 22: return fill(py::array(dtype, shape, strides)); + case 23: return fill(arr_t(shape)); + case 24: return py::array(shape, ptr); // can't have nullptr due to templated ctor + case 25: return fill(py::array(dtype, shape)); + case 26: return fill(arr_t(buf_ndim2_null)); + case 27: return fill(py::array(buf_ndim2_null)); // shape: (6, ) - case 8: return arr_t(6, ptr); - case 9: return py::array(6, ptr); - case 10: return py::array(dtype, 6, vptr); - case 11: return arr_t(buf_ndim1); - case 12: return py::array(buf_ndim1); + case 30: return arr_t(6, ptr); + case 31: return py::array(6, ptr); + case 32: return py::array(dtype, 6, vptr); + case 33: return arr_t(buf_ndim1); + case 34: return py::array(buf_ndim1); + // shape: (6, ) + case 40: return fill(arr_t(6)); + case 41: return py::array(6, ptr); // can't have nullptr due to templated ctor + case 42: return fill(py::array(dtype, 6)); + case 43: return fill(arr_t(buf_ndim1_null)); + case 44: return fill(py::array(buf_ndim1_null)); } return arr_t(); } diff --git a/example/example-numpy-dtypes.py b/example/example-numpy-dtypes.py index 2c90ed286..7858acd46 100644 --- a/example/example-numpy-dtypes.py +++ b/example/example-numpy-dtypes.py @@ -83,9 +83,12 @@ arr = create_string_array(False) assert dtype == arr.dtype data = np.arange(1, 7, dtype='int32') -for i in range(13): - expected = data if i >= 8 else data.reshape((3, 2)) - np.testing.assert_array_equal(test_array_ctors(i), expected) +for i in range(8): + np.testing.assert_array_equal(test_array_ctors(10 + i), data.reshape((3, 2))) + np.testing.assert_array_equal(test_array_ctors(20 + i), data.reshape((3, 2))) +for i in range(5): + np.testing.assert_array_equal(test_array_ctors(30 + i), data) + np.testing.assert_array_equal(test_array_ctors(40 + i), data) d1 = np.dtype({'names': ['a', 'b'], 'formats': ['int32', 'float64'], 'offsets': [1, 10], 'itemsize': 20}) diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index d7b697f9a..b9ee69e6c 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -212,7 +212,7 @@ public: }; array(const pybind11::dtype& dt, const std::vector& shape, - void *ptr, const std::vector& strides) { + const std::vector& strides, void *ptr = nullptr) { auto& api = detail::npy_api::get(); auto ndim = shape.size(); if (shape.size() != strides.size()) @@ -228,30 +228,24 @@ public: m_ptr = tmp.release().ptr(); } - array(const pybind11::dtype& dt, const std::vector& shape, void *ptr) - : array(dt, shape, ptr, default_strides(shape, dt.itemsize())) - { } + array(const pybind11::dtype& dt, const std::vector& shape, void *ptr = nullptr) + : array(dt, shape, default_strides(shape, dt.itemsize()), ptr) { } - array(const pybind11::dtype& dt, size_t size, void *ptr) - : array(dt, std::vector { size }, ptr) - { } + array(const pybind11::dtype& dt, size_t size, void *ptr = nullptr) + : array(dt, std::vector { size }, ptr) { } template array(const std::vector& shape, - T* ptr, const std::vector& strides) - : array(pybind11::dtype::of(), shape, (void *) ptr, strides) - { } + const std::vector& strides, T* ptr) + : array(pybind11::dtype::of(), shape, strides, (void *) ptr) { } template array(const std::vector& shape, T* ptr) - : array(shape, ptr, default_strides(shape, sizeof(T))) - { } + : array(shape, default_strides(shape, sizeof(T)), ptr) { } template array(size_t size, T* ptr) - : array(std::vector { size }, ptr) - { } + : array(std::vector { size }, ptr) { } array(const buffer_info &info) - : array(pybind11::dtype(info), info.shape, info.ptr, info.strides) - { } + : array(pybind11::dtype(info), info.shape, info.strides, info.ptr) { } pybind11::dtype dtype() { return attr("dtype").cast(); @@ -281,17 +275,17 @@ public: array_t(const buffer_info& info) : array(info) { } - array_t(const std::vector& shape, - T* ptr, const std::vector& strides) - : array(shape, ptr, strides) { } + array_t(const std::vector& shape, const std::vector& strides, T* ptr = nullptr) + : array(shape, strides, ptr) { } - array_t(const std::vector& shape, T* ptr) + array_t(const std::vector& shape, T* ptr = nullptr) : array(shape, ptr) { } - array_t(size_t size, T* ptr) + array_t(size_t size, T* ptr = nullptr) : array(size, ptr) { } static bool is_non_null(PyObject *ptr) { return ptr != nullptr; } + static PyObject *ensure(PyObject *ptr) { if (ptr == nullptr) return nullptr;