huziyu123
huziyu123

Reputation: 21

How to convert c_int_array into python list?

I am using the ctypes at python3.8 to call C++ function, the function parameter is an array, and its returns to an array as well. So I create the python list first, then convert it to C++ array to call the function.

ll = ctypes.cdll.LoadLibrary
lib = ll('./ct.so')

nums = [0, 1, 2, 3]
arr = (ctypes.c_int * len(nums))(*nums)
nums2 = lib.method01(arr)

As you can see, nums is a python list, and I convert it to C++ array by using ctypes, get arr. Then I get a C++ array nums2 by calling lib.method01(arr).

Since nums2 is a C++ array, so the print(nums2) get the result like this: __main__.c_int_Array_4, which is not a python array. So is there anything can do to transfer c++ array to python array?

Thanks

Upvotes: 2

Views: 723

Answers (2)

Mark Tolonen
Mark Tolonen

Reputation: 177755

Just call list(nums2). Example:

>>> from ctypes import *
>>> nums = [0,1,2,3]
>>> arr = (c_int*4)(*nums)
>>> arr
<__main__.c_long_Array_4 object at 0x00000217CE89F7C8>
>>> list(arr)
[0, 1, 2, 3]

Note this also works if your API returns a pointer as well, but needs string slicing since the total length must also be known:

>>> p = cast(arr,POINTER(c_int))
>>> p
<__main__.LP_c_long object at 0x00000217CE89F948>
>>> p.contents
c_long(0)
>>> p[0]
0
>>> p[3]
3
>>> p[4] # undefined behavior...past end of array.
0
>>> p[:4]  # slice to known size
[0, 1, 2, 3]

FYI, as @user2357112 points out, slicing is ~4.5x faster:

In [1]: from ctypes import *
In [2]: nums = list(range(5000))
In [3]: arr = (c_int*5000)(*nums)
In [4]: %timeit list(arr)
454 µs ± 9.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [5]: %timeit arr[:]
107 µs ± 2.32 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Upvotes: 2

user2357112
user2357112

Reputation: 281151

Slice it:

as_list = nums2[:]

This runs faster than calling list. (I don't think the slice-returns-a-list behavior is documented anywhere in the ctypes docs.)

Upvotes: 0

Related Questions