python ctypes
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<stdlib.h> #include<stdio.h> struct Point { int x; char *y; }; extern "C" { int take1(int a); void take2(char *); Point * take3(Point *a); void take4(void (*fp)(int), int arg){fp(arg);} }
// file: testlib.cpp #include"testlib.h" int take1(int a) { 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); return a; }
to build it : g++ -std=c++11 -fpic -shared testlib.c -o libtestlib.so
python script which involks libtestlib.so
#!/usr/bin/python3 from 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 a new 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") class Child: 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 exported for DLLS 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 is a 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) class POINT(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 = 5 databuf = (c_char * charlen)() for i in range(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()