引言
前段時間在作信號分析處理方面的項目時,需要將時域數據通過快速傅立葉變換(FFT)轉換到頻域以便作進一步的後續處理,由於涉及到實時運算速度方面的要求,需要考慮程序算法的運算性能問題,因此,信號處理算法是在C語言裡面完成的,然後將算法的實現函數封裝到動態連結庫(DLL)文件中,最後在Python中調用該DLL文件中的函數,通過GUI界面程序對運算結果作圖形的顯示等工作。這兒就涉及到了如何將C語言中的複數數組(Complex array)類型與Python中的數據類型進行交互的問題。
在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,前面多篇文章中已經講了傳遞數值/指針/字符串參數、傳遞結構體參數、傳遞普通數組類型的例子,大家可以回看一下,這樣可以更好的理解本次要講的內容。
這次的例子運行環境配置如下:
① 作業系統:win7 64位
② Python版本:python2.7.14
③ 函數約定的調用方式:C調用(cdecl)方式。
下面給出具體的實現過程。
函數說明
在DLL文件(MyDLL.dll)中設計一個函數ComplexArrayFunc,其功能是,對於輸入長度為n的複數數組x,將x數組中的每個複數元素的實部和虛部進行交換,得到同樣長度的複數數組y。該函數的聲明如下圖所示:
函數ComplexArrayFunc的具體C語言實現代碼如下:
下面給出Python中轉為numpy數組的調用方法。
Python中調用方法
如果像前面幾篇文章中所示,考慮將上面函數中複數數組x直接使用ctypes模塊聲明為複數類型的指針,即形如「POINT(c_double)」的形式,但是,在ctypes模塊中聲明指針的類型時,該模塊中沒有c_complex類型的指針,所以這種方式不容易實現。
一般情況下,在C語言與Python語言通過DLL文件進行混合編程時,可將DLL函數中的數組類型轉換為numpy庫裡面的數組類型,這樣做的好處是可以藉助於numpy強大的分析處理功能對數據直接作後續處理。
在numpy庫中,直接支持複數數組類型的聲明。
按照這種思路,在Python中的函數聲明及調用方式如下:
上面方法在聲明函數的參數類型時,對於參數x和y複數類型的指針變量,使用np.ctypeslib.ndpointer(dtype=np.complex128,ndim=1,flags="C_CONTIGUOUS")直接將numpy中的數組聲明為C語言中的複數數組類型,最後調用時,將numpy中的數組類型a和b傳到該函數中即可。
需要說明的是,複數類型的指針x和y,其類型要聲明為np.complex128,因為在C語言中,其實部和虛部都是為double類型(8個字節)的數據,所以對應numpy中的複數類型為8*2=16Bytes=128bits。
在Python中使用這種調用方法的優點是,只需在文件中對函數原型聲明一次即可,雖然在聲明時麻煩些,但可以在Python中多個地方多次調用該函數,且可以直接使用numpy中的數組類型,無需做另外的轉換工作。
完整的測試代碼
完整的測試代碼如下圖所示:
運行結果如下圖所示:
從運行結果可以看出,對於包含3個複數元素的數組a,已經實現了其實部和虛部進行交換的目的,通過複數數組b進行了正確的輸出。這種調用方法可以實現C語言複數數組與numpy複數數組之間數據正確的傳遞。
總結
從這個例子中可以看出,在Python語言中,通過ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,在提高軟體運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟體的功能及應用領域,減少重複編寫代碼、重複造輪子的工作量,這也充分體現了Python語言作為一種膠水語言所特有的優勢。
本文由編碼那些事原創,請關注+轉發+收藏+點讚,帶你一起長知識!