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