mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-26 15:12:01 +00:00
Add a few comments throughout numpy.h
This commit is contained in:
parent
2f01f01866
commit
3b803846d5
@ -123,20 +123,29 @@ public:
|
|||||||
PyObject *arr = nullptr, *descr = nullptr;
|
PyObject *arr = nullptr, *descr = nullptr;
|
||||||
int ndim = 0;
|
int ndim = 0;
|
||||||
Py_ssize_t dims[32];
|
Py_ssize_t dims[32];
|
||||||
|
API& api = lookup_api();
|
||||||
|
|
||||||
// allocate zeroed memory if it hasn't been provided
|
// Allocate zeroed memory if it hasn't been provided by the caller.
|
||||||
|
// Normally, we could leave this null for NumPy to allocate memory for us, but
|
||||||
|
// since we need a memoryview, the data pointer has to be non-null. NumPy uses
|
||||||
|
// malloc if NPY_NEEDS_INIT is not set (in which case it uses calloc); however,
|
||||||
|
// we don't have a descriptor yet (only a buffer format string), so we can't
|
||||||
|
// access the flags. The safest thing to do is thus to use calloc.
|
||||||
auto buf_info = info;
|
auto buf_info = info;
|
||||||
if (!buf_info.ptr)
|
if (!buf_info.ptr)
|
||||||
// always allocate at least 1 element, same way as NumPy does it
|
// always allocate at least 1 element, same way as NumPy does it
|
||||||
buf_info.ptr = std::calloc(std::max(info.size, 1ul), info.itemsize);
|
buf_info.ptr = std::calloc(std::max(info.size, 1ul), info.itemsize);
|
||||||
if (!buf_info.ptr)
|
if (!buf_info.ptr)
|
||||||
pybind11_fail("NumPy: failed to allocate memory for buffer");
|
pybind11_fail("NumPy: failed to allocate memory for buffer");
|
||||||
auto view = memoryview(buf_info);
|
|
||||||
|
|
||||||
API& api = lookup_api();
|
// PyArray_GetArrayParamsFromObject seems to be the only low-level API function
|
||||||
|
// that will accept arbitrary buffers (including structured types)
|
||||||
|
auto view = memoryview(buf_info);
|
||||||
auto res = api.PyArray_GetArrayParamsFromObject_(view.ptr(), nullptr, 1, &descr,
|
auto res = api.PyArray_GetArrayParamsFromObject_(view.ptr(), nullptr, 1, &descr,
|
||||||
&ndim, dims, &arr, nullptr);
|
&ndim, dims, &arr, nullptr);
|
||||||
if (res < 0 || !arr || descr)
|
if (res < 0 || !arr || descr)
|
||||||
|
// We expect arr to have a pointer to a newly created array, in which case all
|
||||||
|
// other parameters like descr would be set to null, according to the API.
|
||||||
pybind11_fail("NumPy: unable to convert buffer to an array");
|
pybind11_fail("NumPy: unable to convert buffer to an array");
|
||||||
m_ptr = arr;
|
m_ptr = arr;
|
||||||
}
|
}
|
||||||
@ -161,7 +170,8 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
API &api = lookup_api();
|
API &api = lookup_api();
|
||||||
PyObject *descr = detail::npy_format_descriptor<T>::dtype().release().ptr();
|
PyObject *descr = detail::npy_format_descriptor<T>::dtype().release().ptr();
|
||||||
PyObject *result = api.PyArray_FromAny_(ptr, descr, 0, 0, API::NPY_ENSURE_ARRAY_ | ExtraFlags, nullptr);
|
PyObject *result = api.PyArray_FromAny_(ptr, descr, 0, 0,
|
||||||
|
API::NPY_ENSURE_ARRAY_ | ExtraFlags, nullptr);
|
||||||
if (!result)
|
if (!result)
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
Py_DECREF(ptr);
|
Py_DECREF(ptr);
|
||||||
@ -254,8 +264,11 @@ struct npy_format_descriptor<T, typename std::enable_if<is_pod_struct<T>::value>
|
|||||||
args["names"] = names;
|
args["names"] = names;
|
||||||
args["offsets"] = offsets;
|
args["offsets"] = offsets;
|
||||||
args["formats"] = formats;
|
args["formats"] = formats;
|
||||||
|
// This is essentially the same as calling np.dtype() constructor in Python and passing
|
||||||
|
// it a dict of the form {'names': ..., 'formats': ..., 'offsets': ...}.
|
||||||
if (!api.PyArray_DescrConverter_(args.release().ptr(), &dtype_()) || !dtype_())
|
if (!api.PyArray_DescrConverter_(args.release().ptr(), &dtype_()) || !dtype_())
|
||||||
pybind11_fail("NumPy: failed to create structured dtype");
|
pybind11_fail("NumPy: failed to create structured dtype");
|
||||||
|
// Let NumPy figure the buffer format string for us: memoryview(np.empty(0, dtype)).format
|
||||||
auto np = module::import("numpy");
|
auto np = module::import("numpy");
|
||||||
auto empty = (object) np.attr("empty");
|
auto empty = (object) np.attr("empty");
|
||||||
if (auto arr = (object) empty(int_(0), dtype())) {
|
if (auto arr = (object) empty(int_(0), dtype())) {
|
||||||
@ -274,6 +287,7 @@ private:
|
|||||||
static inline char* format_() { static char s[4096]; return s; }
|
static inline char* format_() { static char s[4096]; return s; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Extract name, offset and format descriptor for a struct field
|
||||||
#define PYBIND11_FIELD_DESCRIPTOR(Type, Field) \
|
#define PYBIND11_FIELD_DESCRIPTOR(Type, Field) \
|
||||||
::pybind11::detail::field_descriptor { \
|
::pybind11::detail::field_descriptor { \
|
||||||
#Field, offsetof(Type, Field), \
|
#Field, offsetof(Type, Field), \
|
||||||
@ -295,7 +309,7 @@ private:
|
|||||||
#define PYBIND11_MAP_NEXT0(test, next, ...) next PYBIND11_MAP_OUT
|
#define PYBIND11_MAP_NEXT0(test, next, ...) next PYBIND11_MAP_OUT
|
||||||
#define PYBIND11_MAP_NEXT1(test, next) PYBIND11_MAP_NEXT0 (test, next, 0)
|
#define PYBIND11_MAP_NEXT1(test, next) PYBIND11_MAP_NEXT0 (test, next, 0)
|
||||||
#define PYBIND11_MAP_NEXT(test, next) PYBIND11_MAP_NEXT1 (PYBIND11_MAP_GET_END test, next)
|
#define PYBIND11_MAP_NEXT(test, next) PYBIND11_MAP_NEXT1 (PYBIND11_MAP_GET_END test, next)
|
||||||
#ifdef _MSC_VER // MSVC is not as eager to expand macros
|
#ifdef _MSC_VER // MSVC is not as eager to expand macros, hence this workaround
|
||||||
#define PYBIND11_MAP_LIST_NEXT1(test, next) \
|
#define PYBIND11_MAP_LIST_NEXT1(test, next) \
|
||||||
PYBIND11_EVAL0 (PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0))
|
PYBIND11_EVAL0 (PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0))
|
||||||
#else
|
#else
|
||||||
@ -308,6 +322,7 @@ private:
|
|||||||
f(t, x) PYBIND11_MAP_LIST_NEXT (peek, PYBIND11_MAP_LIST1) (f, t, peek, __VA_ARGS__)
|
f(t, x) PYBIND11_MAP_LIST_NEXT (peek, PYBIND11_MAP_LIST1) (f, t, peek, __VA_ARGS__)
|
||||||
#define PYBIND11_MAP_LIST1(f, t, x, peek, ...) \
|
#define PYBIND11_MAP_LIST1(f, t, x, peek, ...) \
|
||||||
f(t, x) PYBIND11_MAP_LIST_NEXT (peek, PYBIND11_MAP_LIST0) (f, t, peek, __VA_ARGS__)
|
f(t, x) PYBIND11_MAP_LIST_NEXT (peek, PYBIND11_MAP_LIST0) (f, t, peek, __VA_ARGS__)
|
||||||
|
// PYBIND11_MAP_LIST(f, t, a1, a2, ...) expands to f(t, a1), f(t, a2), ...
|
||||||
#define PYBIND11_MAP_LIST(f, t, ...) \
|
#define PYBIND11_MAP_LIST(f, t, ...) \
|
||||||
PYBIND11_EVAL (PYBIND11_MAP_LIST1 (f, t, __VA_ARGS__, (), 0))
|
PYBIND11_EVAL (PYBIND11_MAP_LIST1 (f, t, __VA_ARGS__, (), 0))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user