<p dir="auto">The casting of a <code class="notranslate">ctypes</code> Structure object array to numpy array usually results with a numpy structured array. But if the Structure contains a <code class="notranslate">c_wchar</code> array (string) field it becomes an object. I could not find the reason why this is happening.</p>
<p dir="auto">Example:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import numpy as np
import ctypes

class A(ctypes.Structure):
    _fields_ = [('s', ctypes.c_wchar * 5)]

np.array((A*2)())
# array([&lt;__main__.A object at 0x7fa99678f9d8&gt;,
#       &lt;__main__.A object at 0x7fa98804f1e0&gt;], dtype=object)"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">numpy</span> <span class="pl-k">as</span> <span class="pl-s1">np</span>
<span class="pl-k">import</span> <span class="pl-s1">ctypes</span>

<span class="pl-k">class</span> <span class="pl-v">A</span>(<span class="pl-s1">ctypes</span>.<span class="pl-v">Structure</span>):
    <span class="pl-s1">_fields_</span> <span class="pl-c1">=</span> [(<span class="pl-s">'s'</span>, <span class="pl-s1">ctypes</span>.<span class="pl-s1">c_wchar</span> <span class="pl-c1">*</span> <span class="pl-c1">5</span>)]

<span class="pl-s1">np</span>.<span class="pl-en">array</span>((<span class="pl-v">A</span><span class="pl-c1">*</span><span class="pl-c1">2</span>)())
<span class="pl-c"># array([&lt;__main__.A object at 0x7fa99678f9d8&gt;,</span>
<span class="pl-c">#       &lt;__main__.A object at 0x7fa98804f1e0&gt;], dtype=object)</span></pre></div>
<p dir="auto">While:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class B(ctypes.Structure):
    _fields_ = [('s', ctypes.c_char * 5)]

np.array((B*2)())
# array([([b'', b'', b'', b'', b''],), ([b'', b'', b'', b'', b''],)],
#      dtype=[('s', 'S1', (5,))])"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-v">B</span>(<span class="pl-s1">ctypes</span>.<span class="pl-v">Structure</span>):
    <span class="pl-s1">_fields_</span> <span class="pl-c1">=</span> [(<span class="pl-s">'s'</span>, <span class="pl-s1">ctypes</span>.<span class="pl-s1">c_char</span> <span class="pl-c1">*</span> <span class="pl-c1">5</span>)]

<span class="pl-s1">np</span>.<span class="pl-en">array</span>((<span class="pl-v">B</span><span class="pl-c1">*</span><span class="pl-c1">2</span>)())
<span class="pl-c"># array([([b'', b'', b'', b'', b''],), ([b'', b'', b'', b'', b''],)],</span>
<span class="pl-c">#      dtype=[('s', 'S1', (5,))])</span></pre></div>
<p dir="auto">Environment:<br>
Python 3.6, numpy 1.13.1, Ubuntu 16.04</p>
<p dir="auto">The following minimal example crashes with numpy 1.14 and python 2.7.5:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="import numpy
a = numpy.zeros(64)
numpy.save(&quot;/tmp/a.npy&quot;, a)"><pre class="notranslate"><code class="notranslate">import numpy
a = numpy.zeros(64)
numpy.save("/tmp/a.npy", a)
</code></pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="lib/python2.7/site-packages/numpy/lib/format.pyc in _write_array_header(fp, d, version)
    306     header.append(&quot;}&quot;)
    307     header = &quot;&quot;.join(header)
--&gt; 308     header = asbytes(_filter_header(header))
    309 
    310     hlen = len(header) + 1 # 1 for newline

lib/python2.7/site-packages/numpy/lib/format.pyc in _filter_header(s)
    465             tokens.append(token)
    466         last_token_was_number = (token_type == tokenize.NUMBER)
--&gt; 467     return tokenize.untokenize(tokens)
    468 
    469

/usr/lib64/python2.7/tokenize.pyc in untokenize(iterable)
    260     &quot;&quot;&quot;
    261     ut = Untokenizer()
--&gt; 262     return ut.untokenize(iterable)
    263 
    264 def generate_tokens(readline):

/usr/lib64/python2.7/tokenize.pyc in untokenize(self, iterable)
    196                 break
    197             tok_type, token, start, end, line = t
--&gt; 198             self.add_whitespace(start)
    199             self.tokens.append(token)
    200             self.prev_row, self.prev_col = end

/usr/lib64/python2.7/tokenize.pyc in add_whitespace(self, start)
    185     def add_whitespace(self, start):
    186         row, col = start
--&gt; 187         assert row &lt;= self.prev_row
    188         col_offset = col - self.prev_col
    189         if col_offset:

AssertionError:"><pre class="notranslate"><code class="notranslate">lib/python2.7/site-packages/numpy/lib/format.pyc in _write_array_header(fp, d, version)
    306     header.append("}")
    307     header = "".join(header)
--&gt; 308     header = asbytes(_filter_header(header))
    309 
    310     hlen = len(header) + 1 # 1 for newline

lib/python2.7/site-packages/numpy/lib/format.pyc in _filter_header(s)
    465             tokens.append(token)
    466         last_token_was_number = (token_type == tokenize.NUMBER)
--&gt; 467     return tokenize.untokenize(tokens)
    468 
    469

/usr/lib64/python2.7/tokenize.pyc in untokenize(iterable)
    260     """
    261     ut = Untokenizer()
--&gt; 262     return ut.untokenize(iterable)
    263 
    264 def generate_tokens(readline):

/usr/lib64/python2.7/tokenize.pyc in untokenize(self, iterable)
    196                 break
    197             tok_type, token, start, end, line = t
--&gt; 198             self.add_whitespace(start)
    199             self.tokens.append(token)
    200             self.prev_row, self.prev_col = end

/usr/lib64/python2.7/tokenize.pyc in add_whitespace(self, start)
    185     def add_whitespace(self, start):
    186         row, col = start
--&gt; 187         assert row &lt;= self.prev_row
    188         col_offset = col - self.prev_col
    189         if col_offset:

AssertionError:
</code></pre></div>
<p dir="auto">The tokenize is now performed before the padding and the newline is added to the header string. This does not seem to work in python 2.7. Adding the newline in _filter_header(s) fixes the problem for python 2.7, but does not work in python 3. This could be done in the version distinguishing part of _filter_header(s). I am not familiar with the numpy internals and the recent change for the 64 byte alignment (<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="225248510" data-permission-text="Title is private" data-url="https://github.com/numpy/numpy/issues/9025" data-hovercard-type="pull_request" data-hovercard-url="/numpy/numpy/pull/9025/hovercard" href="https://github.com/numpy/numpy/pull/9025">#9025</a>), so I do not feel comfortable to change it myself.</p>