cppyabm  1.0.17
An agent-based library to integrate C++ and Python
buffer_info.h
Go to the documentation of this file.
1 /*
2  pybind11/buffer_info.h: Python buffer object interface
3 
4  Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
5 
6  All rights reserved. Use of this source code is governed by a
7  BSD-style license that can be found in the LICENSE file.
8 */
9 
10 #pragma once
11 
12 #include "detail/common.h"
13 
15 
17 
18 // Default, C-style strides
19 inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
20  auto ndim = shape.size();
21  std::vector<ssize_t> strides(ndim, itemsize);
22  if (ndim > 0)
23  for (size_t i = ndim - 1; i > 0; --i)
24  strides[i - 1] = strides[i] * shape[i];
25  return strides;
26 }
27 
28 // F-style strides; default when constructing an array_t with `ExtraFlags & f_style`
29 inline std::vector<ssize_t> f_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
30  auto ndim = shape.size();
31  std::vector<ssize_t> strides(ndim, itemsize);
32  for (size_t i = 1; i < ndim; ++i)
33  strides[i] = strides[i - 1] * shape[i - 1];
34  return strides;
35 }
36 
38 
39 /// Information record describing a Python buffer object
40 struct buffer_info {
41  void *ptr = nullptr; // Pointer to the underlying storage
42  ssize_t itemsize = 0; // Size of individual items in bytes
43  ssize_t size = 0; // Total number of entries
44  std::string format; // For homogeneous buffers, this should be set to format_descriptor<T>::format()
45  ssize_t ndim = 0; // Number of dimensions
46  std::vector<ssize_t> shape; // Shape of the tensor (1 entry per dimension)
47  std::vector<ssize_t> strides; // Number of bytes between adjacent entries (for each per dimension)
48  bool readonly = false; // flag to indicate if the underlying storage may be written to
49 
50  buffer_info() = default;
51 
52  buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
53  detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in, bool readonly=false)
54  : ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim),
55  shape(std::move(shape_in)), strides(std::move(strides_in)), readonly(readonly) {
56  if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size())
57  pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length");
58  for (size_t i = 0; i < (size_t) ndim; ++i)
59  size *= shape[i];
60  }
61 
62  template <typename T>
63  buffer_info(T *ptr, detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in, bool readonly=false)
64  : buffer_info(private_ctr_tag(), ptr, sizeof(T), format_descriptor<T>::format(), static_cast<ssize_t>(shape_in->size()), std::move(shape_in), std::move(strides_in), readonly) { }
65 
66  buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t size, bool readonly=false)
67  : buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}, readonly) { }
68 
69  template <typename T>
70  buffer_info(T *ptr, ssize_t size, bool readonly=false)
71  : buffer_info(ptr, sizeof(T), format_descriptor<T>::format(), size, readonly) { }
72 
73  template <typename T>
74  buffer_info(const T *ptr, ssize_t size, bool readonly=true)
75  : buffer_info(const_cast<T*>(ptr), sizeof(T), format_descriptor<T>::format(), size, readonly) { }
76 
77  explicit buffer_info(Py_buffer *view, bool ownview = true)
78  : buffer_info(view->buf, view->itemsize, view->format, view->ndim,
79  {view->shape, view->shape + view->ndim},
80  /* Though buffer::request() requests PyBUF_STRIDES, ctypes objects
81  * ignore this flag and return a view with NULL strides.
82  * When strides are NULL, build them manually. */
83  view->strides
84  ? std::vector<ssize_t>(view->strides, view->strides + view->ndim)
85  : detail::c_strides({view->shape, view->shape + view->ndim}, view->itemsize),
86  view->readonly) {
87  this->m_view = view;
88  this->ownview = ownview;
89  }
90 
91  buffer_info(const buffer_info &) = delete;
92  buffer_info& operator=(const buffer_info &) = delete;
93 
95  (*this) = std::move(other);
96  }
97 
99  ptr = rhs.ptr;
100  itemsize = rhs.itemsize;
101  size = rhs.size;
102  format = std::move(rhs.format);
103  ndim = rhs.ndim;
104  shape = std::move(rhs.shape);
105  strides = std::move(rhs.strides);
106  std::swap(m_view, rhs.m_view);
107  std::swap(ownview, rhs.ownview);
108  readonly = rhs.readonly;
109  return *this;
110  }
111 
113  if (m_view && ownview) { PyBuffer_Release(m_view); delete m_view; }
114  }
115 
116  Py_buffer *view() const { return m_view; }
117  Py_buffer *&view() { return m_view; }
118 private:
119  struct private_ctr_tag { };
120 
121  buffer_info(private_ctr_tag, void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
122  detail::any_container<ssize_t> &&shape_in, detail::any_container<ssize_t> &&strides_in, bool readonly)
123  : buffer_info(ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in), readonly) { }
124 
125  Py_buffer *m_view = nullptr;
126  bool ownview = false;
127 };
128 
130 
131 template <typename T, typename SFINAE = void> struct compare_buffer_info {
132  static bool compare(const buffer_info& b) {
133  return b.format == format_descriptor<T>::format() && b.itemsize == (ssize_t) sizeof(T);
134  }
135 };
136 
137 template <typename T> struct compare_buffer_info<T, detail::enable_if_t<std::is_integral<T>::value>> {
138  static bool compare(const buffer_info& b) {
139  return (size_t) b.itemsize == sizeof(T) && (b.format == format_descriptor<T>::value ||
140  ((sizeof(T) == sizeof(long)) && b.format == (std::is_unsigned<T>::value ? "L" : "l")) ||
141  ((sizeof(T) == sizeof(size_t)) && b.format == (std::is_unsigned<T>::value ? "N" : "n")));
142  }
143 };
144 
buffer_info::view
Py_buffer *& view()
Definition: buffer_info.h:117
buffer_info::buffer_info
buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim, detail::any_container< ssize_t > shape_in, detail::any_container< ssize_t > strides_in, bool readonly=false)
Definition: buffer_info.h:52
enable_if_t
typename std::enable_if< B, T >::type enable_if_t
from cpp_future import (convenient aliases from C++14/17)
Definition: common.h:504
test_multiple_inheritance.i
i
Definition: test_multiple_inheritance.py:22
format_descriptor
Definition: common.h:754
common.h
PYBIND11_NAMESPACE_BEGIN
#define PYBIND11_NAMESPACE_BEGIN(name)
Definition: common.h:16
PYBIND11_NAMESPACE_END
#define PYBIND11_NAMESPACE_END(name)
Definition: common.h:17
buffer_info::buffer_info
buffer_info(const buffer_info &)=delete
buffer_info::buffer_info
buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t size, bool readonly=false)
Definition: buffer_info.h:66
PYBIND11_NAMESPACE
#define PYBIND11_NAMESPACE
Definition: common.h:26
f_strides
std::vector< ssize_t > f_strides(const std::vector< ssize_t > &shape, ssize_t itemsize)
Definition: buffer_info.h:29
buffer_info::~buffer_info
~buffer_info()
Definition: buffer_info.h:112
buffer_info::buffer_info
buffer_info(buffer_info &&other)
Definition: buffer_info.h:94
buffer_info::format
std::string format
Definition: buffer_info.h:44
buffer_info::buffer_info
buffer_info(Py_buffer *view, bool ownview=true)
Definition: buffer_info.h:77
buffer_info::buffer_info
buffer_info(const T *ptr, ssize_t size, bool readonly=true)
Definition: buffer_info.h:74
buffer_info::itemsize
ssize_t itemsize
Definition: buffer_info.h:42
buffer_info::shape
std::vector< ssize_t > shape
Definition: buffer_info.h:46
ssize_t
Py_ssize_t ssize_t
Definition: common.h:353
size_t
std::size_t size_t
Definition: common.h:354
buffer_info::operator=
buffer_info & operator=(buffer_info &&rhs)
Definition: buffer_info.h:98
compare_buffer_info< T, detail::enable_if_t< std::is_integral< T >::value > >::compare
static bool compare(const buffer_info &b)
Definition: buffer_info.h:138
pybind11_fail
PyExc_RuntimeError PYBIND11_NOINLINE void pybind11_fail(const char *reason)
Used internally.
Definition: common.h:751
move
detail::enable_if_t<!detail::move_never< T >::value, T > move(object &&obj)
Definition: cast.h:1798
benchmark.size
size
Definition: benchmark.py:90
buffer_info
Information record describing a Python buffer object.
Definition: buffer_info.h:40
buffer_info::ptr
void * ptr
Definition: buffer_info.h:41
compare_buffer_info::compare
static bool compare(const buffer_info &b)
Definition: buffer_info.h:132
buffer_info::buffer_info
buffer_info(T *ptr, detail::any_container< ssize_t > shape_in, detail::any_container< ssize_t > strides_in, bool readonly=false)
Definition: buffer_info.h:63
compare_buffer_info
Definition: buffer_info.h:131
buffer_info::strides
std::vector< ssize_t > strides
Definition: buffer_info.h:47
c_strides
std::vector< ssize_t > c_strides(const std::vector< ssize_t > &shape, ssize_t itemsize)
Definition: buffer_info.h:19
test_callbacks.value
value
Definition: test_callbacks.py:126
buffer_info::operator=
buffer_info & operator=(const buffer_info &)=delete
buffer_info::buffer_info
buffer_info(T *ptr, ssize_t size, bool readonly=false)
Definition: buffer_info.h:70
buffer_info::buffer_info
buffer_info()=default
buffer_info::view
Py_buffer * view() const
Definition: buffer_info.h:116