在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態鏈接庫DLL文件中的函數,在提高軟件運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟件的功能及應用領域,減少重復編寫代碼、重復造輪子的工作量,這也充分體現了Python語言作為一種膠水語言所特有的優勢。
前面兩篇已經講了傳遞數值/指針/字符串參數、傳遞結構體參數的例子,大家可以回看一下,這樣可以更好的理解本次要講的內容。詳細細節請參考:python使用ctypes模塊調用DLL函數之傳遞數值、指針與字符串參數、Python使用ctypes模塊調用DLL函數之傳遞結構體參數
這次講一下在Python中使用ctypes模塊調用DLL中的庫函數傳遞數組參數的情況。一般情況下,DLL函數中傳遞C語言類型的數組,在接收到Python語言中時,通常將其轉換為numpy庫里面的數組類型,這樣做的好處是可以借助于numpy強大的分析處理功能對數據直接作后續處理。這次通過例子演示下C語言數組到numpy數組之間是怎樣傳遞的。
同樣,操作系統環境是win7 64位,Python使用的版本是python2.7.14,函數約定的調用方式為C調用(cdecl)方式。
例子說明
在DLL文件中設計一個函數GenSine,其功能是根據給定的參數(包括數據點數N、信號頻率f、采樣頻率Fs、信號幅值A、初始相位initPhase、偏移offset等參數)產生一個正弦波形數據,返回時間向量數組x(橫坐標數據)和波形數據y(縱坐標數據)。該函數的聲明如下圖所示:
函數GenSine的具體C語言實現代碼如下:
下面給出兩種Python中轉為numpy數組的調用方法。
Python中調用方法1
在Python中的調用方式如下:
上面的代碼中在聲明函數的參數類型時,對于前兩個參數x和y數組變量,將其聲明為指向double類型的指針即可。在調用該函數時,先聲明兩個numpy庫中的數組t1、y1,數據類型為float64,將其作為參數傳遞到該函數中時,使用的是numpy中的ctypes.data_as(POINT(c_double))轉化為C語言中的指向double類型的指針類型,這樣就可以實現numpy中數組與C語言數組中的完美轉換。
Python中調用方法2
在Python中的調用方式如下:
與第1種方法不同的是,這種方法在聲明函數的參數類型時,對于前兩個參數x和y數組變量,使用np.ctypeslib.ndpointer(dtype=np.float64,ndim=1,flags="C_CONTIGUOUS")直接將numpy中的數組聲明為C語言中的數組類型,最后調用時,直接將將numpy中的數組類型t2和y2傳到該函數中即可。相比于第1種方法,雖然在聲明時麻煩些,但在調用時可以直接使用numpy中的數組類型,相對來說要簡潔些,畢竟函數聲明只需聲明一次即可,但調用函數可能會在程序中出現多次。
完整的測試代碼
在測試程序中,使用了pyqtgraph庫畫兩種方法產生的正弦波形圖,不明白的可以翻看下前面的文章,專門介紹了該庫的畫圖方法。詳細可參考:Python使用pyqtgraph庫實現數據可視化之多條曲線繪制方法
完整的測試代碼如下圖所示:
運行結果如下圖所示:
從運行結果可以看出,兩種調用方法,都可以實現C語言數組與numpy數組之間數據正確的傳遞。相比來說,第2種方法更簡潔些。
歡迎加關注,共同交流。