summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2018-11-13 08:28:27 -0600
committerGitHub <noreply@github.com>2018-11-13 08:28:27 -0600
commit50aa81362c9b81e4cc4926fd23adc7af6971a165 (patch)
tree9a64d0ba97b1391ef7ecc7ce4977e6b9fc9c2e52 /numpy/core
parentbefaf680328cfed7086cb30ccacf1589c2270842 (diff)
parentd176283eae62de443112769e5e8ad165a9f961ac (diff)
downloadnumpy-50aa81362c9b81e4cc4926fd23adc7af6971a165.tar.gz
Merge pull request #12342 from bmakos/fix#10532
BUG: Fix for np.dtype(ctypes.Structure) does not respect _pack_ field
Diffstat (limited to 'numpy/core')
-rw-r--r--numpy/core/_dtype_ctypes.py33
-rw-r--r--numpy/core/tests/test_dtype.py20
2 files changed, 46 insertions, 7 deletions
diff --git a/numpy/core/_dtype_ctypes.py b/numpy/core/_dtype_ctypes.py
index f10b4e99f..b6e4ddf9e 100644
--- a/numpy/core/_dtype_ctypes.py
+++ b/numpy/core/_dtype_ctypes.py
@@ -33,17 +33,38 @@ def _from_ctypes_array(t):
def _from_ctypes_structure(t):
- # TODO: gh-10533, gh-10532
- fields = []
+ # TODO: gh-10533
for item in t._fields_:
if len(item) > 2:
raise TypeError(
"ctypes bitfields have no dtype equivalent")
- fname, ftyp = item
- fields.append((fname, dtype_from_ctypes_type(ftyp)))
- # by default, ctypes structs are aligned
- return np.dtype(fields, align=True)
+ if hasattr(t, "_pack_"):
+ formats = []
+ offsets = []
+ names = []
+ current_offset = 0
+ for fname, ftyp in t._fields_:
+ names.append(fname)
+ formats.append(dtype_from_ctypes_type(ftyp))
+ # Each type has a default offset, this is platform dependent for some types.
+ effective_pack = min(t._pack_, ctypes.alignment(ftyp))
+ current_offset = ((current_offset + effective_pack - 1) // effective_pack) * effective_pack
+ offsets.append(current_offset)
+ current_offset += ctypes.sizeof(ftyp)
+
+ return np.dtype(dict(
+ formats=formats,
+ offsets=offsets,
+ names=names,
+ itemsize=ctypes.sizeof(t)))
+ else:
+ fields = []
+ for fname, ftyp in t._fields_:
+ fields.append((fname, dtype_from_ctypes_type(ftyp)))
+
+ # by default, ctypes structs are aligned
+ return np.dtype(fields, align=True)
def dtype_from_ctypes_type(t):
diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py
index ecb51f72d..cfb67f592 100644
--- a/numpy/core/tests/test_dtype.py
+++ b/numpy/core/tests/test_dtype.py
@@ -824,7 +824,6 @@ class TestFromCTypes(object):
))
self.check(Union, expected)
- @pytest.mark.xfail(reason="_pack_ is ignored - see gh-11651")
def test_packed_structure(self):
class PackedStructure(ctypes.Structure):
_pack_ = 1
@@ -838,6 +837,25 @@ class TestFromCTypes(object):
])
self.check(PackedStructure, expected)
+ def test_large_packed_structure(self):
+ class PackedStructure(ctypes.Structure):
+ _pack_ = 2
+ _fields_ = [
+ ('a', ctypes.c_uint8),
+ ('b', ctypes.c_uint16),
+ ('c', ctypes.c_uint8),
+ ('d', ctypes.c_uint16),
+ ('e', ctypes.c_uint32),
+ ('f', ctypes.c_uint32),
+ ('g', ctypes.c_uint8)
+ ]
+ expected = np.dtype(dict(
+ formats=[np.uint8, np.uint16, np.uint8, np.uint16, np.uint32, np.uint32, np.uint8 ],
+ offsets=[0, 2, 4, 6, 8, 12, 16],
+ names=['a', 'b', 'c', 'd', 'e', 'f', 'g'],
+ itemsize=18))
+ self.check(PackedStructure, expected)
+
@pytest.mark.xfail(sys.byteorder != 'little',
reason="non-native endianness does not work - see gh-10533")
def test_little_endian_structure(self):