Only mark unaligned types in buffers (#505)
Previously all types are marked unaligned in buffer format strings,
now we test for alignment before adding the '=' marker.
diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h
index 72dd4b3..2ba7bcc 100644
--- a/include/pybind11/numpy.h
+++ b/include/pybind11/numpy.h
@@ -756,6 +756,7 @@
const char *name;
size_t offset;
size_t size;
+ size_t alignment;
std::string format;
dtype descr;
};
@@ -796,8 +797,10 @@
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 @@
#define PYBIND11_FIELD_DESCRIPTOR_EX(T, Field, Name) \
::pybind11::detail::field_descriptor { \
Name, offsetof(T, Field), sizeof(decltype(std::declval<T>().Field)), \
+ alignof(decltype(std::declval<T>().Field)), \
::pybind11::format_descriptor<decltype(std::declval<T>().Field)>::format(), \
::pybind11::detail::npy_format_descriptor<decltype(std::declval<T>().Field)>::dtype() \
}
diff --git a/tests/test_numpy_dtypes.py b/tests/test_numpy_dtypes.py
index 2ef6f4d..861a5e6 100644
--- a/tests/test_numpy_dtypes.py
+++ b/tests/test_numpy_dtypes.py
@@ -30,13 +30,13 @@
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:}'
]