C integration - part 1


In [ ]:

C integration - part 2


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)


10
100
Python
Python

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)


10
20
30

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


10
20

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)


(5.0, 3.5)
(0, 4)
(4, 4)

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)


(10, 10)
<Field type=c_long, ofs=0, size=4>
<Field type=c_short, ofs=0, size=2>

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)


([10, 20, 0, 0, 0, 0, 0, 0, 0, 0], 3)
<Field type=c_long_Array_10, ofs=0, size=40>
<Field type=c_long, ofs=40, size=4>

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)


[1, 2, 3, 4, 5]

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)


<Field type=Point_Array_3, ofs=0, size=24>

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 )


(<Field type=c_long, ofs=0:0, bits=1>, <Field type=c_long, ofs=0:1, bits=3>)

In [ ]: