I understand that multiplying
a ctype
with an integer
is declaring an array.
For example, ctypes.c_int * 4
is an array of 4 integers.
Then what is py_object
?
Please help me understand how does ctypes.c_int
differs from ctypes.py_object?
Trying to execute
will generate a
TypeError: an integer is required (got type str)
.This is because we have specified that we want an array of three elements, all of which are integers, but we have attempted to include a string inside the array as well.
Arrays, unlike lists, require that all elements
a[0], a[1], ... , a[n]
are of the same type.By specifying
py_object
instead ofc_int
, you are essentially permitted to have an array of arbitrary Python objects, as opposed to only integers.Strictly speaking (in CPython), internally, the
py_object
way gives you an array of pointers to thePyObject
datatype. Internally, all object types are extensions ofPyObject
.So the type of all the elements of the
b
array is pointer toPyObject
. A pointer is nothing more than a memory address. So every element of theb
array is just a memory address pointing to some arbitrary object in Python. Internally, integer, floats, lists, dictionaries, and so on are allPyObject
s so an array with elements of typepy_object
allows for its elements to be memory addresses that refer to essentially any kind of object in Python (lists, tuples, integers, floats, and so on).When we print
b[0]
, for example, Python gives us'Pizza'
as output. Internally, Python uses the memory address of the string object and returns the string for us.Pointers / memory addresses are used frequently in C and in the CPython source code. Python essentially hides memory addresses from us as it is a high-level language, abstracting away from low-level concepts such as pointers.
I hope this helps!