diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2018-11-13 08:28:27 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-13 08:28:27 -0600 |
commit | 50aa81362c9b81e4cc4926fd23adc7af6971a165 (patch) | |
tree | 9a64d0ba97b1391ef7ecc7ce4977e6b9fc9c2e52 /numpy/core | |
parent | befaf680328cfed7086cb30ccacf1589c2270842 (diff) | |
parent | d176283eae62de443112769e5e8ad165a9f961ac (diff) | |
download | numpy-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.py | 33 | ||||
-rw-r--r-- | numpy/core/tests/test_dtype.py | 20 |
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): |