python使用ctypes模塊調用DLL函數之傳遞數值、指針與字符串參數

2020-12-14 編碼那些事

在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,在提高軟體運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟體的功能及應用領域,減少重複編寫代碼、重複造輪子的工作量,這也充分體現了Python語言作為一種膠水語言所特有的優勢。

這次以具體的例子講一下在Python中,如何使用ctypes模塊調用DLL中的庫函數。本文的編程系統環境是win7 64位,Python使用的版本是python2.7.14。

由於DLL中函數中傳遞的參數類型比較多樣化,擬打算分三次講解這部分內容,這次先講傳遞數值、指針與字符串參數的情況,後面再分兩次講解傳遞結構體、數值數組等類型的情況。

DLL文件的加載

假定已經有了一個DLL文件「MyDll.dll」,其函數約定的調用方式為C調用(cdecl)方式,則Python中加載該dll文件的代碼如下:

其中,第1行是引入ctypes模塊,第2行是採用C調用約定加載「MyDll.dll」文件,並將返回值賦給dll變量,後續調用該DLL文件中的函數時,會使用該變量定義要使用的具體函數。

另外,需要說明的是,若DLL函數的調用約定是標準調用約定(stdcall)方式,則DLL文件的加載代碼改為如下:

dll = WinDLL('MyDll.dll')

DLL函數的調用——函數參數為數值情況

如對於「MyDll.dll」文件中的函數add,其函數聲明如下:

該函數有兩個int類型的輸入參數數x和y,返回的兩個數的和。其C語言的實現代碼如下:

在Python中的調用方式如下:

這個函數應該說是最簡單的一個函數了,在第17行,直接使用第一步加載DLL後返回的名稱dll,後面跟函數名字即可返回其值。

DLL函數的調用——函數參數為指針情況

對於上面的函數改進為add2,其函數C語言的實現代碼如下:

此時函數有三個指向int類型的指針參數x、y、z,z為x和y的和。

在Python中的調用方式如下:

其中,第20-22行定義了3個int型的變量x、y和z,初始值分別為2,3,0。第23行調用add2函數時,使用byref指明參數傳遞時為引用傳遞,對應著C語言的指針傳遞。函數運行後,使用z.value即可查看z的值。

也可以使用下面的代碼調用:

上面代碼中,第23-24行,在使用add2函數時,先將函數賦給一個變量add2,然後對其輸入輸出參數進行單獨聲明,使用POINTER聲明為這三個參數為指向int類型的指針變量。

DLL函數的調用——函數參數為字符串情況

例1:如對於下面的函數,返回一個輸入字符串的字節長度,其函數C語言的實現代碼如下:

在Python中的調用代碼如下:

其中,第33行使用c_char_p定義了一個指向char型的指針變量pStr,並賦初值為』abcdef』,第34行將其傳入GetStringLength函數返回其長度。

也可以使用下面代碼調用:

將GetStringLength函數的輸入輸出參數分別使用argtypes和restype單獨進行聲明。

例2:如對於下面的函數,輸入輸出皆為字符串指針,函數的功能是對於輸入pStr1賦值為「StrIn」,對於輸出返回一個指向字符串常量「strOut」的指針,其函數C語言的實現代碼如下:

在Python中的調用代碼如下:

在上面代碼中,同樣分別對輸入輸出參數進行了聲明。對於輸入參數pStr,使用create_string_buffer函數定義了一個字符串緩衝區。對於返回值pChar,在列印輸出結果時,將其強制轉換為c_char_p類型,取其value值即可。

完整的測試代碼

完整的測試代碼如下圖所示:

運行結果如下圖所示:

總結

這次的例子基本涵蓋了在Python中通過ctypes模塊調用DLL函數時,傳遞數值、指針、字符串類型參數時的大部分情況。要注意的是,使用ctypes映射C語言中的數據類型時,兩者必須完全一致。下面是Python的ctypes模塊中數據類型與C語言中數據類型對照表:

歡迎加關注,共同交流。

相關焦點

  • Python使用ctypes模塊調用DLL函數之複數數組的參數傳遞
    在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,前面多篇文章中已經講了傳遞數值/指針/字符串參數、傳遞結構體參數、傳遞普通數組類型的例子,大家可以回看一下,這樣可以更好的理解本次要講的內容。
  • Python使用ctypes模塊調用DLL函數之傳遞結構體參數
    在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,在提高軟體運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟體的功能及應用領域,減少重複編寫代碼、重複造輪子的工作量,這也充分體現了Python語言作為一種膠水語言所特有的優勢
  • Python使用ctypes模塊調用DLL函數之C語言數組與numpy數組傳遞
    前面兩篇已經講了傳遞數值/指針/字符串參數、傳遞結構體參數的例子,大家可以回看一下,這樣可以更好的理解本次要講的內容。詳細細節請參考:python使用ctypes模塊調用DLL函數之傳遞數值、指針與字符串參數、
  • Python 通過 ctypes 調用 C 程序實例
    使用C標準庫函數我們來試試調用C標準庫函數:from ctypes import cdlllibc = cdll.LoadLibrary('libc.so.6')  # Load standard C library on Linux# libc = cdll.LoadLibrary('libc.dylib')  # Load standard
  • 加速程序開發 Python整合C語言模塊
    利用ctypes模塊整合Python程序和C程序ctypes模塊ctypes是Python的一個標準模塊,它包含在Python2.3及以上的版本裡。ctypes是一個Python的高級外部函數接口,它使得Python程序可以調用C語言編譯的靜態連結庫和動態連結庫。
  • 使用C++調用python3模塊中的類/函數詳細經驗
    調用函數(含傳參)PyObject* ret_from_python;// 獲取python模塊中的 test_1 函數, 如需調用類,則可以將test_1更換為類名PyObject* func_py= PyDict_GetItemString(mdule_dict, "test_1");// 執行下列函數時,若為函數名,則返回函數中的返回值對象;// 若為類名
  • Python 調用 C 模塊以及性能分析
    和python的數據類型的對應關係ctypes type ctype Python typec_char char 1-character stringc_wchar wchar_t 1-character unicode stringc_byte char int/longc_ubyte unsigned char int/long
  • python3使用ctypes在windows中訪問C和C++動態連結庫函數示例
    python3使用ctypes在windows中訪問C和C++動態連結庫函數示例這是我們的第一個示例,我們儘量簡單,不傳參,不返回,不訪問其他的動態連結庫一 測試環境介紹和準備二 C/C++部分代碼1 首先完成C/C++的動態連結庫,與做python擴展庫不同,ctypes調用的c++庫其實與python沒有代碼關聯,只是提供了開放公共標準。
  • 構建 Python C 擴展模塊
    第一個參數是用戶要調用的函數名稱,第二個是要調用的C函數名稱,第三個是模塊的標示,告訴解釋器函數將接受兩個 PyObject 類型的參數,self 模塊對象和arg 函數的實際參數的元組。第四個就是函數的 docstring ,我們可以通過 help(fputs) 獲取。
  • 如何用 Python 製作一款間諜小程序
    知識點本次我們使用 python 來打造一款間諜程序,程序中會用到許多知識點,大致分為四塊:Python 基礎重點在 cpytes 庫的使用,使用方法連結:https://docs.python.org/3.7/library/ctypes.html程序的基本原理在於通過註冊
  • 如何用 Python 監聽軟體?
    Hook 技術又叫做鉤子函數,系統在調用函數之前,鉤子程序就先捕獲該消息,鉤子函數先得到控制權,這時鉤子函數既可以加工處理(改變)該函數的執行行為,還可以強制結束消息的傳遞註冊Hook時我們需要使用到兩個DLL庫:user32.dll和kernel32.dll。
  • Python函數詳解一(函數參數、變量作用域)
    python除了可以直接使用內置函數,還支持自定義函數。定義函數使用 def 關鍵字,格式如下:函數的返回值函數的返回值用return語句返回,函數體內部的語句在執行時,一旦執行到return時,函數就執行完畢,並將結果返回。如果沒有返回值,函數執行完畢後也會返回結果,只是結果為None。
  • Python入門基礎中怎麼定義函數,函數調用,函數傳遞參數
    語法Python 定義函數使用 def 關鍵字,一般格式如下:函數調用定義一個函數,給了函數一個名稱,指定了函數裡包含的參數,和代碼塊結構。函數調用格式:函數名()參數傳遞在 python 中,類型屬於對象,變量是沒有類型的。參數可以看鑰匙,函數是門,多個參數就是多把 鑰匙,開門需要鑰匙。
  • python+C、C++混合編程的應用
    python與C/C++混合編程的本質是python調用C/C++編譯的動態連結庫,關鍵就是把python中的數據類型轉換成c/c++中的數據類型,給編譯函數處理,然後返回參數再轉換成python中的數據類型。
  • Python每天一分鐘:如何把元組/字典作為參數傳遞給函數(附代碼)
    學習程式語言的讀者對於函數參數的傳遞應該都不陌生,目前業內已經有多種高級語言允許定義個數可變的參數,這樣的好處是可以在調用函數時傳入任意多個參數。python可變參數當然,Python 也不例外,那麼如何在定義函數時支持使用可變參數呢?
  • Python調用VC++的動態連結庫DLL
    首先VC++的DLL的導出函數定義成標準C的導出函數:#ifdef LRDLLTEST_EXPORTS #define LRDLLTEST_API __declspec(dllexport) #else #define LRDLLTEST_API __declspec(dllimport) #endif extern
  • C語言函數指針之回調函數
    我的理解是:把一段可執行的代碼像參數傳遞那樣傳給其他代碼,而這段代碼會在某個時刻被調用執行,這就叫做回調如果代碼立即被執行就稱為同步回調,如果過後再執行,則稱之為異步回調回調函數就是一個通過調用的函數。
  • Python 開發一個間諜小程序
    Hook 技術又叫做鉤子函數,系統在調用函數之前,鉤子程序就先捕獲該消息,鉤子函數先得到控制權,這時鉤子函數既可以加工處理(改變)該函數的執行行為,還可以強制結束消息的傳遞註冊Hook時我們需要先導入DLL庫,在Python中我們使用ctypes來導入,導入方法如下user32 = CDLL("user32.dll")kernel32
  • Python與C/C++之間還可以這樣玩?
    一、問題Python模塊和C/C++的動態庫間相互調用在實際的應用中會有所涉及,在此作一總結。二、Python調用C/C++1、Python調用C動態連結庫Python調用C庫比較簡單,不經過任何封裝打包成so,再使用python的ctypes調用即可。
  • Python案例|混用C函數
    使用Python自帶的 ctypes 模塊在Python內直接調用C的動態連結庫代碼,這對於調用現有的庫,一些不開源的庫很有用.用Python自帶的c API來寫模塊,當然是用c/c++來編寫用 Cython 的新語法來寫擴展模塊,這種新語法看起來既像Python又像C,是個語法混合體,但還有很多人推崇, 其優點是可以同時調用C函數和Python函數。但其語法小編著實看著頭大,有興趣的可以自行研究.