Python使用ctypes模塊調用DLL函數之複數數組的參數傳遞

2021-01-11 編碼那些事

引言

前段時間在作信號分析處理方面的項目時,需要將時域數據通過快速傅立葉變換(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語言作為一種膠水語言所特有的優勢。

本文由編碼那些事原創,請關注+轉發+收藏+點讚,帶你一起長知識!

相關焦點

  • Python使用ctypes模塊調用DLL函數之C語言數組與numpy數組傳遞
    在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,在提高軟體運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟體的功能及應用領域,減少重複編寫代碼、重複造輪子的工作量,這也充分體現了Python語言作為一種膠水語言所特有的優勢
  • 如何獲取numpy數組的真實地址?如何與ctypes數組共享內存?
    02如何與ctypes庫創建的數組共享內存空間?對於Python編程人員來說,ctypes庫也是使用率比較高的一個庫,當調用第三方提供的動態庫連結庫函數時,它經常用於定義與C語言兼容的數據類型變量,作為Python語言與C語言進行數據交互的橋梁。
  • 加快Python算法的四個方法(二)Numba
    首先,numba在首次用作機器代碼後還會緩存這些函數。因此,在第一次使用之後,它會變得更快,因為你無需再次編譯該代碼,因為你使用的參數類型和你之前使用的相同。而且,如果你的代碼是可以並行化運行的,那麼也可以將parallel = True作為參數傳遞,但是必須跟參數nopython = True結合使用。目前,它僅可以在CPU上工作。
  • Python語言中使用array模塊實現動態數組的操作
    背景對於動態數組諸如創建、插入、刪除、查詢大小等操作,在C/C++語言中,可以使用標準庫中的vector類實現,而在python語言中,也同樣提供了內置的array模塊實現類似的功能。下面通過例子講解array模塊的常用操作。動態數組的創建創建方式為:array.array(typecode[, initializer]),第1個參數typecode定義了數組元素的類型,第2個可選參數給出了數組中的初始值。如下面的代碼創建了一個int型的包含3個元素的數組x,其初始值為分別為1、2、3。
  • Python的武器庫05:numpy模塊(下)
    說到程式語言python,有一個著名的格言"餘生太短,只用python"。如果要分析為什麼會存在這麼一句格言?python的語法並不簡單,有複雜難懂的部分,之所以有這樣一句格言,是因為python中有很多強大的模塊,就像一個武器庫。
  • Python不可變數據數字有什麼內置模塊函數可以使用
    我們知道Python中數字有int(整數)、float(浮點數、小數)、bool(布爾值)、complex(複數)。數字需要用到數學運算函數,有些函數可以直接使用,有些函數需要引入模塊。需要哪個模塊。模塊的作用是什麼?abs() 函數返回數字的絕對值。
  • python測試函數模塊unittest
    1.測試函數在編寫完代碼後進行對代碼測試是否有錯誤2.pytho標準庫中的模塊unittest為代碼測試工具例如:name_function.py 模塊名def get_formatted_name(first, last): full_name = first + ' ' + last
  • Python的武器庫04:numpy模塊(上)
    說到程式語言python,有一個著名的格言"餘生太短,只用python"。如果要分析為什麼會存在這麼一句格言?python的語法並不簡單,有複雜難懂的部分,之所以又這樣一句格言,是因為python中有很多強大的模塊,就像一個武器庫。Python正式由於這些模塊的出現,只要引入這個模塊,調用這個模塊的集成函數,問題迎刃而解;不需要從頭開始,節省了大量的時間。
  • Python函數參數的使用方法
    Pyhton函數給編寫程序帶來了便捷性,開發人員可以把程序的共用代碼,或者說是程序的通用功能封裝成函數。當需要使用函數時,只需要在代碼的相應位置調用函數即可。在《初識Python函數編程與代碼的可復用性》一文中,我們已經了解了如何定義一個函數和調用函數。
  • java之數組作為方法參數的使用
    各位小夥伴們大家好,這次小編要介紹的是java作為方法參數,返回值的使用。首先,小編要介紹的是java作為方法參數的使用。1.返回值類型:只是進行列印,不需要進行計算,也沒有結果,用void* 2.方法名稱:printArray* 3.參數列表:必須有數組,才可以列印其中的元素。
  • 打基礎一定要吃透這12類 Python 內置函數
    內置函數就是python給你提供的, 拿來直接用的函數,比如print.,input等。截止到python版本3.6.2 python一共提供了68個內置函數,我將它們分成 12 類,方便你學習。1. 和數字相關1.
  • 一起學JAVA——數組和函數
    可以在一個方法內部調用另外一個方法。方法必須寫在類(class)裡。如果有一段代碼要使用多次,我們可以給它起個名字,每次使用時通過名字調用,這樣就不用每次都寫一大段代碼了。如果某個函數在執行的時候需要調用者傳入數據,那麼可以定義參數列表,用於接收數據。如果函數運行之後需要返回給調用者數據,那麼需要指定返回值類型,並且用關鍵字return返回。定義函數的3個必要條件:函數名、參數列表、返回值類型。
  • python教程之python數學運算
    存儲數據變量#兩個變量交換值,通過第三個參數實現print('兩個變量交換值,通過第三個參數實現'); #第一種方法是通過第三個參數實現x=5;#變量賦值y=11; #變量賦值print('交換前',x,y);temp=x;x=y;y=temp;print
  • 詳解Python在資料庫測試中的應用
    前者使得Python腳本可以直接調用CLR代碼,而後者使得Python可以直接調用任何的JAVA類庫。  相信至此,使用Python作為跨越語言的測試工具的優越性,已經十分明顯了:  對於功能與性能測試,我們只需要自己編寫一個解釋器調用腳本,就可以只需要維護一套測試腳本,而同時可以在任何驅動接口上進行測試,構思大體如下圖所示:
  • python之OS模塊39個常用函數詳解
    作者:小伍哥 來源:AI入門學習os,語義作業系統,所以該模塊就是作業系統相關的功能了,用於處理文件和目錄這些我們日常手動需要做的操作,比如新建文件夾、獲取文件列表、刪除某個文件、獲取文件大小、重命名文件、獲取文件修改時間等,該模塊就包含了大量的作業系統操作函數,精選常用的進行解析,希望對大家有所幫助。
  • 像數組又不是數組:JS函數的參數列表到底是什麼?
    在之前介紹模擬函數重載效果的時候,我們看到JS中的函數中,其實有一個「隱形」的東西來存儲實參所有的實參,這個東西就是arguments對象。但在實際使用過程中它的使用方式和數組簡直一模一樣,用起來感覺就是數組,沒有任何毛病,但實際上它並不是一個數組。
  • Python中的函數參數
    def must(m):# 調用時必須傳入一個參數print("必須傳入參數",m)return# 調用函數,不傳入參數會報錯print(must())># 默認參數:調用時不傳入參數就使用默認值代替def tac(t ="默認值" ):# 調用時不傳入參數,使用默認值print("使用默認值", t)# 調用函數,不傳入參數會使用默認值
  • Python基礎教程(一) - 快速入門
    程序輸入和raw_input()內建函數從用戶得到數據輸入的最好方式使用raw_input()函數,它讀取標準輸入,並將讀取到的數據賦值給指定的變量。有符號整型 - 長整型、布爾值 浮點值 複數Python中字符串被定義為引號之間的字符集合。支持使用成對的單引號或雙引號,三引號(三個連續的單引號或雙引號)可以用來包含特殊字符。使用索引操作符([])和切片操作符([:])可以得到子字符串。索引規則:第一個字符的索引是0,最後一個字符的索引是-1。
  • python sys模塊的常見用法匯總
    python的內置模塊sys,提供了系統相關的一些變量和函數,在實際開發中,常見的有以下幾種用法1.()該函數也可以添加一個參數,默認為0,表示正常退出,其他參數表示非正常退出,支持用字符串來自定義錯誤信息。
  • Python程式設計師最常犯的10個錯誤,你中招了嗎?
    本文供Python高級開發人員參考,Python小白可以參考下面這篇文章:http://www.onlamp.com/pub/a/python/2004/02/05/learn_python.html常見錯誤1:濫用表達式作為函數參數的默認值Python允許開發者指定函數參數的默認值