| 85 | }; |
| 86 | |
| 87 | extern "C" inline int getbuffer(PyObject* obj, Py_buffer* view, int flags) { |
| 88 | std::memset(view, 0, sizeof(Py_buffer)); |
| 89 | auto a = nb::cast<mx::array>(nb::handle(obj)); |
| 90 | |
| 91 | { |
| 92 | nb::gil_scoped_release nogil; |
| 93 | a.eval(); |
| 94 | } |
| 95 | |
| 96 | std::vector<Py_ssize_t> shape(a.shape().begin(), a.shape().end()); |
| 97 | std::vector<Py_ssize_t> strides(a.strides().begin(), a.strides().end()); |
| 98 | for (auto& s : strides) { |
| 99 | s *= a.itemsize(); |
| 100 | } |
| 101 | buffer_info* info = |
| 102 | new buffer_info(buffer_format(a), std::move(shape), std::move(strides)); |
| 103 | |
| 104 | view->obj = obj; |
| 105 | view->ndim = a.ndim(); |
| 106 | view->internal = info; |
| 107 | view->buf = a.data<void>(); |
| 108 | view->itemsize = a.itemsize(); |
| 109 | view->len = a.nbytes(); |
| 110 | view->readonly = false; |
| 111 | if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) { |
| 112 | view->format = const_cast<char*>(info->format.c_str()); |
| 113 | } |
| 114 | if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) { |
| 115 | view->strides = info->strides.data(); |
| 116 | view->shape = info->shape.data(); |
| 117 | } |
| 118 | Py_INCREF(view->obj); |
| 119 | return 0; |
| 120 | } |
| 121 | |
| 122 | extern "C" inline void releasebuffer(PyObject*, Py_buffer* view) { |
| 123 | delete (buffer_info*)view->internal; |
nothing calls this directly
no test coverage detected