通過實例簡介python使用ctypes模塊調用C語言動態庫


看介紹python語言時,說它是膠水語言,可以調用其他語言。通過使用ctypes模塊就可以調用C語言的動態庫。下面先放上官方文檔和幾個比較好的博文。

 

1、官方文檔:http://python.net/crew/theller/ctypes/tutorial.html

2Python調用windowsDLL詳解 - ctypes庫的使用

http://blog.csdn.net/magictong/article/details/3075478

3、聊聊Python ctypes 模塊

https://zhuanlan.zhihu.com/p/20152309

4、Python的學習(三十二)---- ctypes庫的使用整理

http://blog.csdn.net/linda1000/article/details/12623527

5、ctypes使用指南:

http://blog.csdn.net/samdy2008/article/details/52139142

 

因為這個實例,自己也只是簡單使用沒有整明白,所以先把參考的幾個文章列出來。

C語言編譯為動態鏈接庫。Windows下動態鏈接庫的擴展名是dllLinux下是soMac OS X下是dylib

 

Gcc編譯出的動態庫,python調用時,可以直接調用原型,不需要做特殊處理。

VS使用的編譯器是 MSVC,和g++編譯出來的動態庫,需要特珠聲明才能被調用。因為編譯出的函數名實際上不是本來的名字,這也是C++可以重載的原因,真實的函數名已經變了。

頭文件中定義

#ifdef __cplusplus

extern "C" { //這個是必須有的

#endif

/*************************************

*函數功能:打開攝像頭 

不是函數接口,所以不需要特殊處理

*************************************/

INT8U BSP_CameraOpen(INT8U ucPort);

 

/*************************************

*函數功能:獲取圖像

因是接口,需要特殊處理

*************************************/

_declspec(dllexport) INT8U BSP_CameraGetPhoto(INT8U ucFormat,INT8U *pDataBuf,INT16U *pDataLen);

 

/*

拍照片初始化,即創建串口,打開攝像頭,之后就可以直接操作讀照片了。

因是接口,需要特殊處理

*/

 _declspec(dllexport) int ComCamInit(void);

 

#ifdef __cplusplus

};

#endif

 
        

如不特殊處理,python加載庫時不會報錯,但是調用函數接口時,會拋出找不到函數的異常。(編譯庫時,函數名字變了嘛)

 

>>> import ctypes					#導入ctypes庫
>>> testdll = ctypes.CDLL(r"D:\project program\photo\VS_dll\photo_dll\photo_dll.dll")

>>> ret = testdll.ComCamInit()		   #調用庫中的ComCamInit()函數,返回0說明返回成功了。
>>> ret
0

 

庫里的BSP_CameraGetPhoto()函數,參數為INT8U *pDataBuf,INT16U *pDataLen,需要傳入一個數組的指針,用於返回獲取到的圖片數據,和一個short類型的指針用於保存返回的長度。

所以要用到數組的映射和指針的映射,也就是C語言的數據類型轉換為ctypes中的數據類型。

基本類型映射

 

>>>type_uchar_array_20k = ctypes.c_char * (20*1024)  #創建一個20K的char型數組類型type_uchar_array_20k

>>> my_array = type_uchar_array_20k()  #實例化生成這個20K的char型數組的對象

>>> uwlen = 0                       #定義uwlen

>>> uwLenPara= ctypes.c_ushort(uwlen)        #這里可以不使用uwlen,而使用0,這里是要告訴 uwLenPara 的類型和值

>>> ret = testdll.BSP_CameraGetPhoto(1,my_array,ctypes.byref(uwLenPara))

>>> ret

40459264

 

>>> help(ctypes.byref)

Help on built-in function byref in module _ctypes:

 

byref(...)

    byref(C instance[, offset=0]) -> byref-object

    Return a pointer lookalike to a C instance, only usable

    as function argument

Byref關鍵字會這個這個對像的指針。

 

返回結果為40459264(  0x2695C00)

Python中返回的類型默認為int,而庫里這個函數返回的類型是unsigned char所以需要指定返回類型,這里最低字節0x00說明返回成功了。

如果動態鏈接庫中的C函數返回值不是int,需要在調用函數之前顯式的告訴ctypes返回值的類型

testdll.BSP_CameraGetPhoto.restype = ctypes.c_ubyte

>>> ret = testdll.BSP_RearCommClose()  #調用動態庫關閉串口句柄

>>> my_array              #數組對象

<__main__.c_char_Array_20480 object at 0x02695CB0>

>>> my_array.value  #輸出數組的值需要用循環,這里只顯示四個字節(默認按int顯示)

'\xff\xd8\xff\xdb'

>>> uwlen          #說明返回值和uwlen 沒關系,定義uwLenPara時只是使用了uwlen做為初始值

0

>>> uwLenPara      #返回他的類型,和值 6592

c_short(6592)

>>> uwLenPara.value

6592

>>> type_uchar_array_20k         #數組類型(比較my_array返回)

<class '__main__.c_char_Array_20480'>

>>> ctypes.byref(uwLenPara)       #返回一個指針(02695C88)

<cparam 'P' (02695C88)>

 
#把獲取到的圖片數據寫到二進制文件里,

>>> with open(r"D:\test123.jpg",'wb') as f:

            for i in xrange(uwLenPara.value):

                f.write(my_array[i])            

  

 實驗結果:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM