diff options
author | Mircea Akos Bruma <bruma.mircea.a@gmail.com> | 2018-11-08 21:52:32 +0100 |
---|---|---|
committer | Mircea Akos Bruma <bruma.mircea.a@gmail.com> | 2018-11-08 21:52:32 +0100 |
commit | 3ce73b79d6dc151f64f3254f9eeafd681c5efa5c (patch) | |
tree | 9a1db637be635040203d489b469928088ae93bc0 /numpy/core | |
parent | 9ca7cb17cabd2996b17d25357cbc00b41985b58e (diff) | |
download | numpy-3ce73b79d6dc151f64f3254f9eeafd681c5efa5c.tar.gz |
BUG: Fix for np.dtype(ctypes.Structure) does not respect _pack_ field
See #10532
Made several changes to offset and size calulation. First pull request
was far from correct.
Diffstat (limited to 'numpy/core')
-rw-r--r-- | numpy/core/_dtype_ctypes.py | 51 | ||||
-rw-r--r-- | numpy/core/tests/test_dtype.py | 1 |
2 files changed, 33 insertions, 19 deletions
diff --git a/numpy/core/_dtype_ctypes.py b/numpy/core/_dtype_ctypes.py index e6e675e2c..6829860cc 100644 --- a/numpy/core/_dtype_ctypes.py +++ b/numpy/core/_dtype_ctypes.py @@ -34,27 +34,42 @@ def _from_ctypes_array(t): def _from_ctypes_structure(t): # TODO: gh-10533 - if hasattr(t,"_pack_"): - fields = {} - for item in t._fields_: - if len(item) > 2: - raise TypeError( + for item in t._fields_: + if len(item) > 2: + raise TypeError( "ctypes bitfields have no dtype equivalent") - fname, ftyp = item - fields[fname] = dtype_from_ctypes_type(ftyp), t._pack_ - - return np.dtype(fields, align=False) else: - fields = [] - 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))) + if hasattr(t,"_pack_"): + formats_array = [] + offsets_array = [] + names_array = [] + current_offset = 0 + current_itemsize = 0 + for item in t._fields_: + fname, ftyp = item + names_array.append(fname) + formats_array.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_array.append(current_offset) + current_offset += ctypes.sizeof(ftyp) + + + return np.dtype(dict( + formats = formats_array, + offsets = offsets_array, + names = names_array, + itemsize = ctypes.sizeof(t) + )) + else: + fields = [] + for item in t._fields_: + fname, ftyp = item + fields.append((fname, dtype_from_ctypes_type(ftyp))) - # by default, ctypes structs are aligned - return np.dtype(fields, align=True) + # 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..f4b118bab 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 |