ctypes允许通过python代码建立c语言的方法。那么,我们可以在c代码的so里面进行创建一个支持回调的函数。
为方法创建一个类
这个类明白调用原则,返回类型,接受多少个参数。
CFUNTYPE()工厂方法创建cdecl调用标准的方法。
windows平台,WINFUNCTYPE()工厂方法创建的是一个stdcall调用原则的方法。
这几个工厂方法接受的参数说明,第一个是返回参数类型(returnType,arg1,arg2,arg3)
C语言只会返回一个值。
演示一个案例,c语言的标准函数 qsort(),排序方法。
qsort第一个参数是一个指针,表示将要排序的对象数组,n个将要排序的元素,单个元素的大小,排序规则。
qsort(void * array,int n2sort,int sizeofitem,int (*cmp)(void *,void*) )
创建这样一个对象,并且初始化,即通过()调用进行值初始化。
>>> CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
>>> def py_cmp_func(a, b):
... print("py_cmp_func", a[0], b[0])
... return 0
...
>>> cmp_func = CMPFUNC(py_cmp_func)
>>>
调用执行结果
>>> qsort(ia, len(ia), sizeof(c_int), cmp_func)
py_cmp_func 5 1
py_cmp_func 33 99
py_cmp_func 7 33
py_cmp_func 5 7
py_cmp_func 1 7
>>>
迭代遍历排序后的
>>> for i in ia: print(i, end=" ")
...
1 5 7 33 99
>>>
需要记住,由CFUNCTYPE创建的C函数需要尽可能的有一个引用,也就是保持这个函数不被垃圾回收机制回收。
否则在此调用的时候会导致程序崩溃。同样,如果在python程序外的新的线程中调用这个方法,那么ctypes将会为每一个调用创建一个傀儡线程。这个机制适合大部分情景,但是这也意味着,threading.local将不会为这些跨方法的调用了,即使他们是从同一个c线程中创建。