Reputation: 5495
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
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
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:
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