動態連接庫在Windows中爲.dll文件,在linux中爲.so文件。以linux平臺爲例說明python調用.so文件的使用方法。
本例中默認讀者已經掌握動態連接庫的生成方法,若是不太清楚的能夠參考動態連接庫的使用
調用上例動態連接庫的使用中的sum.sohtml
import ctypes so = ctypes.CDLL('./sum.so') print "so.sum(50) = %d" % so.sum(50) so.display("hello world!") print "so.add() = %d" % so.add(ctypes.c_float(2), ctypes.c_float(2010))
outputpython
so.sum(50) = 1275 hello world! so.add() = 2012
注意:linux
import ctypes pyarray = [1, 2, 3, 4, 5] carrary = (ctypes.c_int * len(pyarray))(*pyarray) //有點相似malloc的方式生成carray print so.sum_array(carray, len(pyarray))
refergit
pyarray = [1,2,3,4,5,6,7,8] carray = (ctypes.c_int*len(pyarray))(*pyarray) so.modify_array(carray, len(pyarray)) print np.array(carray)
outputgithub
[10 20 30 40 50 60 70 80]
import ctypes import numpy as np from numpy.ctypeslib import ndpointer so = ctypes.CDLL('./sum.so') pyarray = np.array([1,2,3,4,5,6,7,8], dtype="int32") fun = so.modify_array fun.argtypes = [ndpointer(ctypes.c_int), ctypes.c_int] fun.restype = None fun(pyarray, len(pyarray)) print np.array(pyarray)
注意:numpy中的數據類型指定很重要,即dtype的設定數組
背景知識:
python中的opencv圖片是用numpy的方式保存的,而opencv3 C語言的圖片數據結構爲cvMat (IplImage已經逐棄用)
因此須要把python中numpy圖片轉換爲ctypes.POINTER(ctypes.c_ubyte)的指針轉入其數據域,再將其行列信息傳入,就能夠在C中從最底層初始化一個CvMat,若是要初始化一個別數據結構的圖片也是同理(如darknet的image,caffe的blob)
python numpy image 轉換爲 C pointer的方法數據結構
python_frm.ctypes.data_as(C.POINTER(ctypes.c_ubyte))
注意:傳入numpy image前必定要確保numpy image是numpy array數據類型
好比我遇到的bug函數
image = cv2.imread("xxx.jpg");
image傳入ctypes_so.fun之中圖片是有效的,但3d
image = whl_img[y1:y2, x1:x2]
這時候進入ctypes_so.fun的圖片會變成一個亂碼
即,crop以後的numpy image的type雖然也爲numpy array,但實際傳入的image data卻不正確
解決方法:
不管是何種方式獲得的numpy image,都強行轉換爲numpy array,再傳入ctypes_so.fun指針
image = numpy.array(image)
能夠解決這個bug
refence
opencv3 python已經不支持cv2.cv的函數了
但Opencv2可能還能夠嘗試如下方法
numpy image to iplimage
由於python不能直接調用C++中的類,因此必須把C++中的類轉換爲C的接口
轉換原則
#ifdef __cplusplus extern "C" { #endif xxxxxx function declaration xxxxx #ifdef __cplusplus } #endif