From dbb4c5b531aa53e0a88728049cb650cc07068abd Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Fri, 7 Apr 2017 15:21:53 -0400 Subject: [PATCH] Move buffer_info to its own header Upcoming changes to buffer_info make it need some things declared in common.h; it also feels a bit misplaced in common.h (which is arguably too large already), so move it out. (Separating this and the subsequent changes into separate commits to make the changes easier to distinguish from the move.) --- CMakeLists.txt | 1 + include/pybind11/buffer_info.h | 96 ++++++++++++++++++++++++++++++++++ include/pybind11/common.h | 81 ---------------------------- include/pybind11/pytypes.h | 1 + 4 files changed, 98 insertions(+), 81 deletions(-) create mode 100644 include/pybind11/buffer_info.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 51f9d79a6..8af2f4195 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ set(PYTHON_MODULE_EXTENSION ${PYTHON_MODULE_EXTENSION} CACHE INTERNAL "") set(PYBIND11_HEADERS include/pybind11/attr.h + include/pybind11/buffer_info.h include/pybind11/cast.h include/pybind11/chrono.h include/pybind11/class_support.h diff --git a/include/pybind11/buffer_info.h b/include/pybind11/buffer_info.h new file mode 100644 index 000000000..8bdfc0737 --- /dev/null +++ b/include/pybind11/buffer_info.h @@ -0,0 +1,96 @@ +/* + pybind11/buffer_info.h: Python buffer object interface + + Copyright (c) 2016 Wenzel Jakob + + All rights reserved. Use of this source code is governed by a + BSD-style license that can be found in the LICENSE file. +*/ + +#pragma once + +#include "common.h" + +NAMESPACE_BEGIN(pybind11) + +/// Information record describing a Python buffer object +struct buffer_info { + void *ptr = nullptr; // Pointer to the underlying storage + size_t itemsize = 0; // Size of individual items in bytes + size_t size = 0; // Total number of entries + std::string format; // For homogeneous buffers, this should be set to format_descriptor::format() + size_t ndim = 0; // Number of dimensions + std::vector shape; // Shape of the tensor (1 entry per dimension) + std::vector strides; // Number of entries between adjacent entries (for each per dimension) + + buffer_info() { } + + buffer_info(void *ptr, size_t itemsize, const std::string &format, size_t ndim, + const std::vector &shape, const std::vector &strides) + : ptr(ptr), itemsize(itemsize), size(1), format(format), + ndim(ndim), shape(shape), strides(strides) { + for (size_t i = 0; i < ndim; ++i) + size *= shape[i]; + } + + buffer_info(void *ptr, size_t itemsize, const std::string &format, size_t size) + : buffer_info(ptr, itemsize, format, 1, std::vector { size }, + std::vector { itemsize }) { } + + explicit buffer_info(Py_buffer *view, bool ownview = true) + : ptr(view->buf), itemsize((size_t) view->itemsize), size(1), format(view->format), + ndim((size_t) view->ndim), shape((size_t) view->ndim), strides((size_t) view->ndim), view(view), ownview(ownview) { + for (size_t i = 0; i < (size_t) view->ndim; ++i) { + shape[i] = (size_t) view->shape[i]; + strides[i] = (size_t) view->strides[i]; + size *= shape[i]; + } + } + + buffer_info(const buffer_info &) = delete; + buffer_info& operator=(const buffer_info &) = delete; + + buffer_info(buffer_info &&other) { + (*this) = std::move(other); + } + + buffer_info& operator=(buffer_info &&rhs) { + ptr = rhs.ptr; + itemsize = rhs.itemsize; + size = rhs.size; + format = std::move(rhs.format); + ndim = rhs.ndim; + shape = std::move(rhs.shape); + strides = std::move(rhs.strides); + std::swap(view, rhs.view); + std::swap(ownview, rhs.ownview); + return *this; + } + + ~buffer_info() { + if (view && ownview) { PyBuffer_Release(view); delete view; } + } + +private: + Py_buffer *view = nullptr; + bool ownview = false; +}; + +NAMESPACE_BEGIN(detail) + +template struct compare_buffer_info { + static bool compare(const buffer_info& b) { + return b.format == format_descriptor::format() && b.itemsize == sizeof(T); + } +}; + +template struct compare_buffer_info::value>> { + static bool compare(const buffer_info& b) { + return b.itemsize == sizeof(T) && (b.format == format_descriptor::value || + ((sizeof(T) == sizeof(long)) && b.format == (std::is_unsigned::value ? "L" : "l")) || + ((sizeof(T) == sizeof(size_t)) && b.format == (std::is_unsigned::value ? "N" : "n"))); + } +}; + +NAMESPACE_END(detail) +NAMESPACE_END(pybind11) diff --git a/include/pybind11/common.h b/include/pybind11/common.h index 70743eaca..941842b21 100644 --- a/include/pybind11/common.h +++ b/include/pybind11/common.h @@ -286,69 +286,6 @@ enum class return_value_policy : uint8_t { reference_internal }; -/// Information record describing a Python buffer object -struct buffer_info { - void *ptr = nullptr; // Pointer to the underlying storage - size_t itemsize = 0; // Size of individual items in bytes - size_t size = 0; // Total number of entries - std::string format; // For homogeneous buffers, this should be set to format_descriptor::format() - size_t ndim = 0; // Number of dimensions - std::vector shape; // Shape of the tensor (1 entry per dimension) - std::vector strides; // Number of entries between adjacent entries (for each per dimension) - - buffer_info() { } - - buffer_info(void *ptr, size_t itemsize, const std::string &format, size_t ndim, - const std::vector &shape, const std::vector &strides) - : ptr(ptr), itemsize(itemsize), size(1), format(format), - ndim(ndim), shape(shape), strides(strides) { - for (size_t i = 0; i < ndim; ++i) - size *= shape[i]; - } - - buffer_info(void *ptr, size_t itemsize, const std::string &format, size_t size) - : buffer_info(ptr, itemsize, format, 1, std::vector { size }, - std::vector { itemsize }) { } - - explicit buffer_info(Py_buffer *view, bool ownview = true) - : ptr(view->buf), itemsize((size_t) view->itemsize), size(1), format(view->format), - ndim((size_t) view->ndim), shape((size_t) view->ndim), strides((size_t) view->ndim), view(view), ownview(ownview) { - for (size_t i = 0; i < (size_t) view->ndim; ++i) { - shape[i] = (size_t) view->shape[i]; - strides[i] = (size_t) view->strides[i]; - size *= shape[i]; - } - } - - buffer_info(const buffer_info &) = delete; - buffer_info& operator=(const buffer_info &) = delete; - - buffer_info(buffer_info &&other) { - (*this) = std::move(other); - } - - buffer_info& operator=(buffer_info &&rhs) { - ptr = rhs.ptr; - itemsize = rhs.itemsize; - size = rhs.size; - format = std::move(rhs.format); - ndim = rhs.ndim; - shape = std::move(rhs.shape); - strides = std::move(rhs.strides); - std::swap(view, rhs.view); - std::swap(ownview, rhs.ownview); - return *this; - } - - ~buffer_info() { - if (view && ownview) { PyBuffer_Release(view); delete view; } - } - -private: - Py_buffer *view = nullptr; - bool ownview = false; -}; - NAMESPACE_BEGIN(detail) inline static constexpr int log2(size_t n, int k = 0) { return (n <= 1) ? k : log2(n >> 1, k + 1); } @@ -669,24 +606,6 @@ template struct format_descriptor constexpr const char format_descriptor< T, detail::enable_if_t::value>>::value[2]; -NAMESPACE_BEGIN(detail) - -template struct compare_buffer_info { - static bool compare(const buffer_info& b) { - return b.format == format_descriptor::format() && b.itemsize == sizeof(T); - } -}; - -template struct compare_buffer_info::value>> { - static bool compare(const buffer_info& b) { - return b.itemsize == sizeof(T) && (b.format == format_descriptor::value || - ((sizeof(T) == sizeof(long)) && b.format == (std::is_unsigned::value ? "L" : "l")) || - ((sizeof(T) == sizeof(size_t)) && b.format == (std::is_unsigned::value ? "N" : "n"))); - } -}; - -NAMESPACE_END(detail) - /// RAII wrapper that temporarily clears any Python error state struct error_scope { PyObject *type, *value, *trace; diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index 805b04fcd..b7317df96 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -10,6 +10,7 @@ #pragma once #include "common.h" +#include "buffer_info.h" #include #include