In [ ]:
In [2]:
import ctypes
i = ctypes.c_int(10)
print (i.value)
i.value = 100
print (i.value)
i = ctypes.c_char_p(b"Python") #expects binary in Py3, because ...
print (i.value)
i = ctypes.c_wchar_p("Python") #expects string in Py3
print (i.value)
In [3]:
#ctypes also includes a function called pointer that can create a pointer to another ctypes object.
#In this example, ptr_i is a pointer to the variable i. Each pointer object has a property (contents)
#that give access to the object the pointer points to (in our case, ptr_i.contents is i)
import ctypes
i = ctypes.c_int(10)
ptr_i = ctypes.pointer(i)
print(ptr_i.contents.value)
ptr_i.contents.value = 20
print(i.value)
j = ctypes.c_int(30)
ptr_i.contents = j
print(ptr_i.contents.value)
In [4]:
#References can also be used. ctypes provides a function byref that can be used to obtain a reference to an ctypes object.
#Building a reference is faster in Python that building a pointer. If speed is a concern byref should be used instead of pointer.
import ctypes
i = ctypes.c_int(10)
ref_i = ctypes.byref(i)
print(ref_i._obj.value)
ref_i._obj.value = 20
print(i.value)
j = ctypes.c_int(30)
# ref_i._obj = j #read only, cannot be assigned anymore
In [5]:
#structures can be build and pass as a parameter using ctypes.Structure. Fields will be created just like in a C/C++ structure.
import ctypes
'''
struct Point {
float x;
float y;
}
'''
class Point(ctypes.Structure):
_fields_ = [("x",ctypes.c_float),("y",ctypes.c_float)]
p = Point(1.5,3.5) # if y not given, will be set as 0
p.x += p.y
print(p.x,p.y)
print(Point.x.offset,Point.x.size)
print(Point.y.offset,Point.y.size)
In [6]:
# Union can be used to described a C/C++ union where all the fields start from the same address (occupy the same memory space).
#In this case, as p.i and p.s are 0 from the initialization moment (no values provided to the constructor),
#once p.s becomes 10, the value of p.i will be modified as well (in this case 10).
import ctypes
'''
union CUnion {
long i;
short s;
}
'''
class CUnion(ctypes.Union):
_fields_ = [("i",ctypes.c_long),("s",ctypes.c_short)]
p = CUnion()
p.s = 10
print(p.i,p.s)
print(CUnion.i)
print(CUnion.s)
In [7]:
# In case of ctypes.Structure the operator * can be used to specify a 1-dimensional array of a specific type.
import ctypes
class Numbers(ctypes.Structure):
_fields_ = [("n",ctypes.c_long * 10),("count",ctypes.c_long)]
p = Numbers()
p.n[0] = 10
p.n[1] = 20
s = []
for i in range(0,10):s += [p.n[i]]
p.count = 3
print(s,p.count)
print(Numbers.n)
print(Numbers.count)
In [8]:
#Pointer can also be used in a structure (ctypes provide the POINTER member for this). The default value
#will be NULL so they will have to be instantiated).
import ctypes
'''
struct Numbers {
long *n;
long count;
}
'''
class Numbers(ctypes.Structure):
_fields_ = [("n", ctypes.POINTER(ctypes.c_long)), ("count",ctypes.c_long)]
p = Numbers()
p.n = (ctypes.c_long * 5)(1,2,3,4,5)
p.count = 5
s = []
for i in range(0,p.count):
s += [p.n[i]]
print(s)
In [9]:
#A member in a structure can also be another structure previously defined. This way complex data structure can be created.
import ctypes
'''
struct Point {
float x;
float y;
};
struct Triangle {
Point pct[3];
};
'''
class Point(ctypes.Structure):
_fields_ = [("x",ctypes.c_float), ("y",ctypes.c_float)]
class Triangle(ctypes.Structure):
_fields_ = [("pct",Point * 3)]
t = Triangle()
t.pct[0].x = 10
t.pct[0].y = 20
print (Triangle.pct)
In [10]:
# Bit sets are also possible by adding the 3rd parameter to the tuple used to describer the _fields_ member.
import ctypes
class BitField(ctypes.Structure):
_fields_ = [("bit_0", ctypes.c_int, 1), ("next_3_bytes", ctypes.c_int, 3)]
b = BitField()
b.bit_0 = 1
b.next_3_bytes = 2;
print ( BitField.bit_0, BitField.next_3_bytes )
In [ ]: