动态链接库在Windows中为. dll文件,在linux中为所以文件。以linux平台为例说明python调用。所以文件的使用方法。
本例中默认读者已经掌握动态链接库的生成方法,如果不太清楚的可以参考动态链接库的使用
调用上例动态链接库的使用中的sum.so
进口ctypes 所以=ctypes.CDLL (“。/sum.so”) 打印”so.sum (50)=% d % so.sum (50) 所以。显示(“hello world !”) 打印”so.add ()=% d % so.add (ctypes.c_float (2), ctypes.c_float (2010)
输出
so.sum (50)=1275 你好世界! so.add ()=2012
注意:
-
<李>如果python在调用C函数内部出现了问题,系统不会提示具体出现什么问题,只会提示“段错误”,所以最好是先用C语言调用该动态库验证没有问题了再提供给python调用。李>
<李> python传参给C函数时,可能会因为python传入实参与C函数形参类型不一致会出现问题(一般int,字符串不会有问题,浮动要注意)。这时需要在python调用时传入的实参做一个类型转换(见。添加(浮动,浮动)函数的调用)。转换方式见下表:李>
<强>数组的传入传出强>
如果将python列表中传入C函数数组,则需要提前转换。
进口ctypes pyarray=[1、2、3、4、5) carrary=(ctypes。c_int len (pyarray)) * (* pyarray)//有点类似malloc的方式生成carray 打印。sum_array (carray len (pyarray))
参考
如果如果需要将C数组返回python,需要提前把数组传入,然后在C函数中修改,返回时再把C数组转换为np.array
pyarray=[1, 2, 3, 4, 5, 6, 7, 8) carray=(ctypes.c_int * len (pyarray)) (* pyarray) 所以。modify_array (carray len (pyarray)) 打印np.array (carray)
输出
[10 20 30 40 50 60 70 80]
<强>也可以用形参方式提前定义函数接口,然后再传入numpy结构强>
进口ctypes 进口numpy np 从numpy。ctypeslib进口ndpointer 所以=ctypes.CDLL (“。/sum.so”) pyarray=np。数组([1,2,3,4,5,6,7,8),dtype=癷nt32”) 有趣=so.modify_array 乐趣。argtypes=[ndpointer (ctypes.c_int) ctypes.c_int] 乐趣。restype=没有 有趣(pyarray len (pyarray)) 打印np.array (pyarray)
注意:numpy中的数据类型指定很重要,即dtype的设定
<强>图片的传入传出强>
转递数据域
背景知识:
python中的opencv图片是用numpy的方式保存的,而opencv3 C语言的图片数据结构为cvMat (IplImage已经逐弃用)
所以需要把python中numpy图片转换为ctypes.POINTER (ctypes.c_ubyte)的指针转入其数据域,再将其行列信息传入,就可以在C中从最底层初始化一个CvMat,如果要初始化一个别数据结构的图片也是同理(如darknet的形象,咖啡的blob)
python numpy图像转换为C指针的方法
python_frm.ctypes.data_as (C.POINTER (ctypes.c_ubyte)
注意:传入numpy图像前一定要确保numpy形象是numpy数组数据类型
比如我遇到的错误
形象=cv2.imread (“xxx.jpg”);
图像传入ctypes_so.fun之中图片是有效的,但
形象=cv2.imread (“xxx.jpg”);
这时候进入ctypes_so。有趣的图片会变成一个乱码
即、作物之后的numpy形象的类型虽然也为numpy数组,但实际传入的图像数据却不正确
解决方法:
无论是何种方式得到的numpy形象,都强行转换为numpy数组,再传入ctypes_so.fun
形象=numpy.array(图片)
可以解决这个bug
参考
<>强如果使用opencv2可以考虑直接将numpy图像转换为IplImage 强>
opencv3 python已经不支持cv2。简历的函数了
但Opencv2可能还可以尝试以下方法
numpy图像iplimage