summaryrefslogtreecommitdiff
path: root/numpy/core
diff options
context:
space:
mode:
authorMircea Akos Bruma <bruma.mircea.a@gmail.com>2018-11-08 21:52:32 +0100
committerMircea Akos Bruma <bruma.mircea.a@gmail.com>2018-11-08 21:52:32 +0100
commit3ce73b79d6dc151f64f3254f9eeafd681c5efa5c (patch)
tree9a1db637be635040203d489b469928088ae93bc0 /numpy/core
parent9ca7cb17cabd2996b17d25357cbc00b41985b58e (diff)
downloadnumpy-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.py51
-rw-r--r--numpy/core/tests/test_dtype.py1
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