python調用.so

python調用動態連接庫的基本過程

動態連接庫在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

  • 若是python在調用C函數內部出現了問題,系統不會提示具體出現什麼問題,只會提示"segmentation fault"。因此最好是先用C語言調用該動態庫驗證沒有問題了再提供給python調用。
  • python傳參給C函數時,可能會由於python傳入實參與C函數形參類型不一致會出現問題( 通常int, string不會有問題,float要注意 )。這時須要在python調用時傳入的實參作一個類型轉換(見so.add(float, float)函數的調用)。轉換方式見下表:

args|center

數組的傳入傳出

若是將python中list傳入C函數數組,則須要提早轉換。

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

若是若是須要將C array返回python,須要提早把array傳入,而後在C函數中修改,返回時再把c array轉換爲np.array

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]

也能夠用形參方式提早定義函數接口,而後再傳入numpy結構

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

若是使用opencv2 能夠考慮直接將numpy image轉換爲IplImage

opencv3 python已經不支持cv2.cv的函數了
但Opencv2可能還能夠嘗試如下方法
numpy image to iplimage

python調用C++中的類

由於python不能直接調用C++中的類,因此必須把C++中的類轉換爲C的接口
轉換原則

  • 全部的C++關鍵字及其特有的使用方式均不能出如今.h文件裏,.h中僅有C函數的包裝函數聲明
  • 在class.cpp中實現對類的成員函數接口轉換的函數,包括對類內成員的讀寫函數get() and set()
  • 若是要在包裝函數中要實例化對象,儘可能用new constructor()的將對象的內存實例化在堆中,不然對象會被析構
  • 記得在全部包含函數聲明的文件中加入如下關鍵字,聲明該函數爲C函數,不然該函數的符號不會記錄在二進制文件中
#ifdef __cplusplus
extern "C" {
#endif
xxxxxx function declaration xxxxx
#ifdef __cplusplus
}
#endif

code
refer
refer

相關文章
相關標籤/搜索