简体   繁体   中英

What does (ctypes.c_int * len(x))(*x) do?

I am working with pyOpenGL, and OpenGL requires me to transfer data by passing a pointer and the number of bytes to transfer.

I understand that python doesn't store variables in memory the same way c does. I have found the following code that makes my program work:

x = [1, 2, ... ]              # some list
(ctypes.c_int * len(x))(*x)

However I have no idea why it works (and I don't just want to trust that I haven't just gotten lucky with how everything fell into memory). What is this code actually doing?

According to the Python documentation :

The recommended way to create concrete array types is by multiplying any ctypes data type with a positive integer. Alternatively, you can subclass this type and define length and type class variables. Array elements can be read and written using standard subscript and slice accesses; for slice reads, the resulting object is not itself an Array.

Example:

 >>> from ctypes import * >>> TenIntegers = c_int * 10 >>> ii = TenIntegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) >>> print ii <c_long_Array_10 object at 0x...> >>> for i in ii: print i, ... 1 2 3 4 5 6 7 8 9 10 >>> 

So, the first part ctypes.c_int * len(x) creates an array type with len(x) elements:

In [17]: ctypes.c_int * 10
Out[17]: __main__.c_int_Array_10

In [18]: ctypes.c_int * 100
Out[18]: __main__.c_int_Array_100

After the type creation, you should call it and pass array elements:

(ctypes.c_int * len(x))(*x)
#                      ^^^^

Created array type accepts variadic number of elements, so, you should expand list x using the *x form :

In [24]: x = [1, 2, 3]

In [25]: (ctypes.c_int * len(x))(*x)
Out[25]: <__main__.c_int_Array_3 at 0x7f0b34171ae8>

In [26]: list((ctypes.c_int * len(x))(*x))
Out[26]: [1, 2, 3]

In [27]: (ctypes.c_int * len(x))(*x)[1]
Out[27]: 2

You cannot pass x , since __init__ expects integers:

In [28]: (ctypes.c_int * len(x))(x)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-28-ff45cb7481e4> in <module>()
----> 1 (ctypes.c_int * len(x))(x)

TypeError: an integer is required (got type list)

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