mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-26 15:12:01 +00:00
Merge pull request #474 from aldanor/feature/numpy-dtype-ex
Overriding field names when binding structured dtypes
This commit is contained in:
commit
a743ead455
@ -20,6 +20,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
# pragma warning(push)
|
# pragma warning(push)
|
||||||
@ -748,14 +749,16 @@ std::string npy_format_descriptor<T, enable_if_t<is_pod_struct<T>::value>>::form
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
PyObject* npy_format_descriptor<T, enable_if_t<is_pod_struct<T>::value>>::dtype_ptr = nullptr;
|
PyObject* npy_format_descriptor<T, enable_if_t<is_pod_struct<T>::value>>::dtype_ptr = nullptr;
|
||||||
|
|
||||||
// Extract name, offset and format descriptor for a struct field
|
#define PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, Name) \
|
||||||
#define PYBIND11_FIELD_DESCRIPTOR(Type, Field) \
|
|
||||||
::pybind11::detail::field_descriptor { \
|
::pybind11::detail::field_descriptor { \
|
||||||
#Field, offsetof(Type, Field), sizeof(decltype(static_cast<Type*>(0)->Field)), \
|
Name, offsetof(T, Field), sizeof(decltype(std::declval<T>().Field)), \
|
||||||
::pybind11::format_descriptor<decltype(static_cast<Type*>(0)->Field)>::format(), \
|
::pybind11::format_descriptor<decltype(std::declval<T>().Field)>::format(), \
|
||||||
::pybind11::detail::npy_format_descriptor<decltype(static_cast<Type*>(0)->Field)>::dtype() \
|
::pybind11::detail::npy_format_descriptor<decltype(std::declval<T>().Field)>::dtype() \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract name, offset and format descriptor for a struct field
|
||||||
|
#define PYBIND11_FIELD_DESCRIPTOR(T, Field) PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, #Field)
|
||||||
|
|
||||||
// The main idea of this macro is borrowed from https://github.com/swansontec/map-macro
|
// The main idea of this macro is borrowed from https://github.com/swansontec/map-macro
|
||||||
// (C) William Swanson, Paul Fultz
|
// (C) William Swanson, Paul Fultz
|
||||||
#define PYBIND11_EVAL0(...) __VA_ARGS__
|
#define PYBIND11_EVAL0(...) __VA_ARGS__
|
||||||
@ -792,6 +795,27 @@ PyObject* npy_format_descriptor<T, enable_if_t<is_pod_struct<T>::value>>::dtype_
|
|||||||
::pybind11::detail::npy_format_descriptor<Type>::register_dtype \
|
::pybind11::detail::npy_format_descriptor<Type>::register_dtype \
|
||||||
({PYBIND11_MAP_LIST (PYBIND11_FIELD_DESCRIPTOR, Type, __VA_ARGS__)})
|
({PYBIND11_MAP_LIST (PYBIND11_FIELD_DESCRIPTOR, Type, __VA_ARGS__)})
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define PYBIND11_MAP2_LIST_NEXT1(test, next) \
|
||||||
|
PYBIND11_EVAL0 (PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0))
|
||||||
|
#else
|
||||||
|
#define PYBIND11_MAP2_LIST_NEXT1(test, next) \
|
||||||
|
PYBIND11_MAP_NEXT0 (test, PYBIND11_MAP_COMMA next, 0)
|
||||||
|
#endif
|
||||||
|
#define PYBIND11_MAP2_LIST_NEXT(test, next) \
|
||||||
|
PYBIND11_MAP2_LIST_NEXT1 (PYBIND11_MAP_GET_END test, next)
|
||||||
|
#define PYBIND11_MAP2_LIST0(f, t, x1, x2, peek, ...) \
|
||||||
|
f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT (peek, PYBIND11_MAP2_LIST1) (f, t, peek, __VA_ARGS__)
|
||||||
|
#define PYBIND11_MAP2_LIST1(f, t, x1, x2, peek, ...) \
|
||||||
|
f(t, x1, x2) PYBIND11_MAP2_LIST_NEXT (peek, PYBIND11_MAP2_LIST0) (f, t, peek, __VA_ARGS__)
|
||||||
|
// PYBIND11_MAP2_LIST(f, t, a1, a2, ...) expands to f(t, a1, a2), f(t, a3, a4), ...
|
||||||
|
#define PYBIND11_MAP2_LIST(f, t, ...) \
|
||||||
|
PYBIND11_EVAL (PYBIND11_MAP2_LIST1 (f, t, __VA_ARGS__, (), 0))
|
||||||
|
|
||||||
|
#define PYBIND11_NUMPY_DTYPE_EX(Type, ...) \
|
||||||
|
::pybind11::detail::npy_format_descriptor<Type>::register_dtype \
|
||||||
|
({PYBIND11_MAP2_LIST (PYBIND11_FIELD_DESCRIPTOR_EX, Type, __VA_ARGS__)})
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
using array_iterator = typename std::add_pointer<T>::type;
|
using array_iterator = typename std::add_pointer<T>::type;
|
||||||
|
|
||||||
|
@ -67,6 +67,11 @@ struct StringStruct {
|
|||||||
std::array<char, 3> b;
|
std::array<char, 3> b;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PYBIND11_PACKED(struct StructWithUglyNames {
|
||||||
|
int8_t __x__;
|
||||||
|
uint64_t __y__;
|
||||||
|
});
|
||||||
|
|
||||||
enum class E1 : int64_t { A = -1, B = 1 };
|
enum class E1 : int64_t { A = -1, B = 1 };
|
||||||
enum E2 : uint8_t { X = 1, Y = 2 };
|
enum E2 : uint8_t { X = 1, Y = 2 };
|
||||||
|
|
||||||
@ -197,7 +202,8 @@ py::list print_dtypes() {
|
|||||||
py::dtype::of<PartialStruct>().str(),
|
py::dtype::of<PartialStruct>().str(),
|
||||||
py::dtype::of<PartialNestedStruct>().str(),
|
py::dtype::of<PartialNestedStruct>().str(),
|
||||||
py::dtype::of<StringStruct>().str(),
|
py::dtype::of<StringStruct>().str(),
|
||||||
py::dtype::of<EnumStruct>().str()
|
py::dtype::of<EnumStruct>().str(),
|
||||||
|
py::dtype::of<StructWithUglyNames>().str()
|
||||||
};
|
};
|
||||||
auto l = py::list();
|
auto l = py::list();
|
||||||
for (const auto &s : dtypes) {
|
for (const auto &s : dtypes) {
|
||||||
@ -312,6 +318,8 @@ test_initializer numpy_dtypes([](py::module &m) {
|
|||||||
// ... or after
|
// ... or after
|
||||||
py::class_<PackedStruct>(m, "PackedStruct");
|
py::class_<PackedStruct>(m, "PackedStruct");
|
||||||
|
|
||||||
|
PYBIND11_NUMPY_DTYPE_EX(StructWithUglyNames, __x__, "x", __y__, "y");
|
||||||
|
|
||||||
m.def("create_rec_simple", &create_recarray<SimpleStruct>);
|
m.def("create_rec_simple", &create_recarray<SimpleStruct>);
|
||||||
m.def("create_rec_packed", &create_recarray<PackedStruct>);
|
m.def("create_rec_packed", &create_recarray<PackedStruct>);
|
||||||
m.def("create_rec_nested", &create_nested);
|
m.def("create_rec_nested", &create_nested);
|
||||||
|
@ -42,7 +42,8 @@ def test_dtype():
|
|||||||
"{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}",
|
"{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}",
|
||||||
"{'names':['a'], 'formats':[{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}], 'offsets':[8], 'itemsize':40}",
|
"{'names':['a'], 'formats':[{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}], 'offsets':[8], 'itemsize':40}",
|
||||||
"[('a', 'S3'), ('b', 'S3')]",
|
"[('a', 'S3'), ('b', 'S3')]",
|
||||||
"[('e1', '<i8'), ('e2', 'u1')]"
|
"[('e1', '<i8'), ('e2', 'u1')]",
|
||||||
|
"[('x', 'i1'), ('y', '<u8')]"
|
||||||
]
|
]
|
||||||
|
|
||||||
d1 = np.dtype({'names': ['a', 'b'], 'formats': ['int32', 'float64'],
|
d1 = np.dtype({'names': ['a', 'b'], 'formats': ['int32', 'float64'],
|
||||||
|
Loading…
Reference in New Issue
Block a user