diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index 72dd4b371..2ba7bccea 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -756,6 +756,7 @@ struct field_descriptor { const char *name; size_t offset; size_t size; + size_t alignment; std::string format; dtype descr; }; @@ -796,8 +797,10 @@ inline PYBIND11_NOINLINE void register_structured_dtype( for (auto& field : ordered_fields) { if (field.offset > offset) oss << (field.offset - offset) << 'x'; - // note that '=' is required to cover the case of unaligned fields - oss << '=' << field.format << ':' << field.name << ':'; + // mark unaligned fields with '=' + if (field.offset % field.alignment) + oss << '='; + oss << field.format << ':' << field.name << ':'; offset = field.offset + field.size; } if (itemsize > offset) @@ -857,6 +860,7 @@ private: #define PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, Name) \ ::pybind11::detail::field_descriptor { \ Name, offsetof(T, Field), sizeof(decltype(std::declval().Field)), \ + alignof(decltype(std::declval().Field)), \ ::pybind11::format_descriptor().Field)>::format(), \ ::pybind11::detail::npy_format_descriptor().Field)>::dtype() \ } diff --git a/tests/test_numpy_dtypes.py b/tests/test_numpy_dtypes.py index 2ef6f4d0b..861a5e656 100644 --- a/tests/test_numpy_dtypes.py +++ b/tests/test_numpy_dtypes.py @@ -30,13 +30,13 @@ def test_format_descriptors(): assert re.match('^NumPy type info missing for .*UnboundStruct.*$', str(excinfo.value)) assert print_format_descriptors() == [ - "T{=?:x:3x=I:y:=f:z:}", - "T{=?:x:=I:y:=f:z:}", - "T{=T{=?:x:3x=I:y:=f:z:}:a:=T{=?:x:=I:y:=f:z:}:b:}", - "T{=?:x:3x=I:y:=f:z:12x}", - "T{8x=T{=?:x:3x=I:y:=f:z:12x}:a:8x}", - "T{=3s:a:=3s:b:}", - 'T{=q:e1:=B:e2:}' + "T{?:x:3xI:y:f:z:}", + "T{?:x:=I:y:=f:z:}", + "T{T{?:x:3xI:y:f:z:}:a:T{?:x:=I:y:=f:z:}:b:}", + "T{?:x:3xI:y:f:z:12x}", + "T{8xT{?:x:3xI:y:f:z:12x}:a:8x}", + "T{3s:a:3s:b:}", + 'T{q:e1:B:e2:}' ]