简体   繁体   中英

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.

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 .

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')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM