实例描述如何用python组件ctypes调用c的dll中的函数
工具:winpython,vc2010(我认为只要能生成dll的编译工具都行)
步骤1:
新建一个VC的DLL工程zm_funs,实现函数:
1 #include "stdio.h" 2 #include "string.h" 3 4 typedef unsigned char uchar; 5 //__declspec(dllexport) 6 void gen_lbp59img(uchar *pu8Img, uchar *pu8LBP59Img, int dwW, int dwH, uchar *pu8LBP89Table) 7 { 8 int dwRI, dwCI, dwPI; 9 int dwOft, dwVal; 10 int adwOffset8[8] = {-dwW - 1, -dwW, -dwW + 1, 1, dwW + 1, dwW, dwW - 1, -1}; 11 12 memset(pu8LBP59Img, 0, dwW * dwH); 13 14 for (dwRI = 1; dwRI < dwH - 1; dwRI++) 15 { 16 for (dwCI = 1; dwCI < dwW - 1; dwCI++) 17 { 18 dwOft = dwRI * dwW + dwCI; 19 dwVal = 0; 20 for (dwPI = 0; dwPI < 8; dwPI++) 21 { 22 if (pu8Img[dwOft + adwOffset8[dwPI]] > pu8Img[dwOft]) 23 { 24 dwVal += 1 << (7 - dwPI); 25 } 26 } 27 pu8LBP59Img[dwOft] = pu8LBP89Table[dwVal] - 1; 28 } 29 } 30 31 return; 32 }
用def文件或__declspec(dllexport)将函数名gen_lbp59img导出。然后编译成DLL(DLL的名字是zm_funs.dll)。
步骤2:
打开winpython,写一个同名的函数(之所以同名是为了好记)用来准备好要传给DLL中函数的数据:
1 import scipy as sp 2 import ctypes as ct 3 4 zmfuns = ct.CDLL('zm_funs.dll') 5 6 def gen_lbp59img(img, lbptable): 7 sz = img.shape 8 if len(sz) > 2: 9 print 'can''t handle color image.' 10 return 11 imgh, imgw = sz 12 lbpimg = sp.zeros(sz, dtype = sp.uint8) 13 # call gen_lbp59img of c 14 zmfuns.gen_lbp59img(img.ctypes, lbpimg.ctypes, imgw, imgh, lbptable.ctypes) 15 16 return lbpimg
注意,传进去的数据是array中的ctypes。实际上,array中的ctypes记录的是指向array数据的地址。
结果:
经过测度,用python实现gen_lbp59img处理QCIF的灰度图像,需要耗时200ms左右,而用C实现后,耗时不到1.5ms。这差距太大了吧!看来PYTHON虽然方便了编程,但是耗时太可观了!