official tutorial for ctypes lib
https://docs.python.org/3/library/ctypes.html
1 ctypes exports the cdll, and on Windows windll and oledll objects, for loading dynamic link libraries
you should load libs by accessing them AS attrinuts of these objects, each object correspond to one call convention
2 fuctions are accessed as attributres of dll objects
None, integers, bytes objects and (unicode) strings are the only native Python objects that can directly be used as parameters in these function calls
3 Structures and unions must derive from the Structure and Union base classes which are defined in the ctypes
By default, Structure and Union fields are aligned in the same way the C compiler does it
4 ctypes instances are objects containing a memory block plus some descriptors accessing the contents of the memory.
Storing a Python object in the memory block does not store the object itself, instead the contents of the object is stored.
Accessing the contents again constructs a new Python object each time
5 compared to swig, there is no complicated data structure in ctypes, such as class, no class inheritance and polymorphism
code:
//file: testlib.h
#include#include
structPoint
{intx;char *y;
};extern "C"{int take1(inta);void take2(char *);
Point* take3(Point *a);void take4(void (*fp)(int), intarg){fp(arg);}
}
//file: testlib.cpp
#include"testlib.h"
int take1(inta)
{return a+2;
}void take2(char *pst)
{
printf("the inpiut string is %s", pst);
}
Point* take3(Point*a)
{
printf("value of a of this struct is %d\n", a->x);
printf("value of b of this struct is %s\n", a->y);returna;
}
to build it :g++ -std=c++11 -fpic -shared testlib.c -o libtestlib.so
python script which involks libtestlib.so
#!/usr/bin/python3from ctypes import *libc= CDLL('libc.so.6')
def funct1():
print(libc.time(None))
i= c_int(42)
print (i)
str= "hello, world"# i will be anew object, change its value will not affects the value of str
i=c_wchar_p(str)
print(i)
i.value= "HELLO WOLRD"print(i, str)
printf=libc.printf
printf(b"take it, %s\n", b"James")classChild:
def __init__(self, age, name):
self._as_parameter_=age
self.age=age
self.name=name
def funct2():
Tony= Child(3, b"tonny")
printf(b"This little boy is %s, age %d \n", Tony.name, Tony.age)
printf(b"This little boy is %d years old now\n", Tony.age)
strchr=libc.strchr
# specify the required arguments of fuctions exportedforDLLS by setting its argtypes attribute
# printf.argtypes=[c_char_p, c_char_p, c_int, c_double]
#set the return type, ctypes will do the converiton for you, which isa necessary step
strchr.restype=c_char_p
i=c_int()
f=c_float()
s= create_string_buffer(b"\000" * 32)
# byref() pass parameters by reference, or use pointer()
libc.sscanf(b"1 3.24 Hello", b"%d %f %s", byref(i), byref(f), s)
print(i,f,s.value)
libc.sscanf(b"1 3.24 Hello", b"%d %f %s", pointer(i), pointer(f), s)
pi=pointer(i)
print(pi.contents,f,s.value)classPOINT(Structure):
_fields_= [('x', c_int), ('y', c_char_p)]
def __init__(self, x, y):
Structure.__init__(self)
self.x=x
self.y=y
def funct3():
pointa= POINT(3,4)
print(pointa.x+pointa.y)
liba= cdll.LoadLibrary("./libtestlib.so")
def funct4():
print(liba.take1(44))
liba.take2(b"example 2\n")
func3=liba.take3
func3.argtypes=[POINTER(POINT)]
func3.restype=POINTER(POINT)
charlen= 5databuf= (c_char *charlen)()for i inrange(charlen):
databuf[i]=c_char(i*2 +68)
chrlist=cast(databuf, c_char_p)
inputvar=POINT(charlen,chrlist)
outputvar=func3(byref(inputvar))
print(outputvar.contents.x)
CB_FUNTYPE=CFUNCTYPE(None, c_int)
def fooo(arg):
print("the value of arg is", arg)
cb_func=CB_FUNTYPE(fooo);
liba.take4(cb_func,55)
funct4()