M.E.
M.E.

Reputation: 5495

How to convert a ctypes array of c_uint to a numpy array

I have the following ctypes array:

data = (ctypes.c_uint * 100)()

And I want to create a numpy array np_data containing the integer values from ctypes array data (the ctypes array is obviously populated later with values)

I have seen that there is a ctypes interface in numpy (https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.ctypes.html) but as far as I understood this is only to get ctypes from a numpy array and not the opposite.

I can obviously traverse data and populate np_data array items one by one, but I am wondering if there is a more efficient/straightforward way to do achieve this task.

Upvotes: 3

Views: 1842

Answers (2)

CristiFati
CristiFati

Reputation: 41137

You could use [NumPy]: numpy.ctypeslib.as_array(obj, shape=None).

>>> import ctypes as ct
>>> import numpy as np
>>>
>>>
>>> CUIntArr10 = ctypes.c_uint * 10
>>>
>>> ui10 = CUIntArr10(*range(10, 0, -1))
>>>
>>> [e for e in ui10]  # The ctypes array
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>>
>>> np_arr = np.ctypeslib.as_array(ui10)
>>> np_arr  # And the np one
array([10,  9,  8,  7,  6,  5,  4,  3,  2,  1], dtype=uint32)

Didn't get to the specific line of code (nor did I test my assumption), but I have a feeling that the contents copying is done by a single memcpy call, which would make it much faster than doing things "manually" from Python.

Upvotes: 4

ead
ead

Reputation: 34337

Probably the fastest is to use np.frombuffer. It can be used with every object which implements the buffer-protocol, in particular with ctypes-arrays.

The main advantage of np.frombuffer is, that the memory of the ctypes-array isn't copied at all, but shared:

data = (ctypes.c_uint * 100)()
arr = np.frombuffer(data, dtype=np.uint32)
arr.flags
# ...
# OWNDATA : False
# ...

By setting

arr.flags.writable = False

one can ensure, that the data will be not be changed via numpy-array arr.

If copying of data is really necessary, the usual numpy-functionality can be used for arr.


The in @CristiFati's answer proposed np.ctypeslib.as_array seems to be a better way to create a numpy-array:

  • the memory is shared as well - there is no copying involved.
  • the right dtype is used automatically (which is a great thing: it eliminates errors (as in my original post, where I've used np.uint (means 64bit unsigned integer on my machine) instead of np.uint32(which also might not be right on some architectures).

Experimental proof of the above:

arr = np.ctypeslib.as_array(data)
arr.flags
# ...
# OWNDATA : False
# ...
arr.dtype
# dtype('<u4')

Upvotes: 1

Related Questions