引言 在Python語言中,可以使用ctypes模塊調(diào)用其它如C++語言編寫的動態(tài)鏈接庫DLL文件中的函數(shù),在提高軟件運(yùn)行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數(shù),以擴(kuò)充Python軟件的功能及應(yīng)用領(lǐng)域,減少重復(fù)編寫代碼、重復(fù)造輪子的工作量,這也充分體現(xiàn)了Python語言作為一種膠水語言所特有的優(yōu)勢。 這次以具體的例子講一下在Python中,如何使用ctypes模塊調(diào)用DLL中的庫函數(shù)。本文的編程系統(tǒng)環(huán)境是win7 64位,Python使用的版本是python2.7.14。 由于DLL中函數(shù)中傳遞的參數(shù)類型比較多樣化,擬打算分三次講解這部分內(nèi)容,這次先講傳遞數(shù)值、指針與字符串參數(shù)的情況,后面再分兩次講解傳遞結(jié)構(gòu)體、數(shù)值數(shù)組等類型的情況。 DLL文件的加載 假定已經(jīng)有了一個DLL文件“MyDll.dll”,其函數(shù)約定的調(diào)用方式為C調(diào)用(cdecl)方式,則Python中加載該dll文件的代碼如下: 其中,第1行是引入ctypes模塊,第2行是采用C調(diào)用約定加載“MyDll.dll”文件,并將返回值賦給dll變量,后續(xù)調(diào)用該DLL文件中的函數(shù)時,會使用該變量定義要使用的具體函數(shù)。 另外,需要說明的是,若DLL函數(shù)的調(diào)用約定是標(biāo)準(zhǔn)調(diào)用約定(stdcall)方式,則DLL文件的加載代碼改為如下: dll = WinDLL(''MyDll.dll'') DLL函數(shù)的調(diào)用——函數(shù)參數(shù)為數(shù)值情況 如對于“MyDll.dll”文件中的函數(shù)add,其函數(shù)聲明如下: 該函數(shù)有兩個int類型的輸入?yún)?shù)數(shù)x和y,返回的兩個數(shù)的和。其C語言的實(shí)現(xiàn)代碼如下: 在Python中的調(diào)用方式如下: 這個函數(shù)應(yīng)該說是最簡單的一個函數(shù)了,在第17行,直接使用第一步加載DLL后返回的名稱dll,后面跟函數(shù)名字即可返回其值。 DLL函數(shù)的調(diào)用——函數(shù)參數(shù)為指針情況 對于上面的函數(shù)改進(jìn)為add2,其函數(shù)C語言的實(shí)現(xiàn)代碼如下: 此時函數(shù)有三個指向int類型的指針參數(shù)x、y、z,z為x和y的和。 在Python中的調(diào)用方式如下: 其中,第20-22行定義了3個int型的變量x、y和z,初始值分別為2,3,0。第23行調(diào)用add2函數(shù)時,使用byref指明參數(shù)傳遞時為引用傳遞,對應(yīng)著C語言的指針傳遞。函數(shù)運(yùn)行后,使用z.value即可查看z的值。 也可以使用下面的代碼調(diào)用: 上面代碼中,第23-24行,在使用add2函數(shù)時,先將函數(shù)賦給一個變量add2,然后對其輸入輸出參數(shù)進(jìn)行單獨(dú)聲明,使用POINTER聲明為這三個參數(shù)為指向int類型的指針變量。 DLL函數(shù)的調(diào)用——函數(shù)參數(shù)為字符串情況 例1:如對于下面的函數(shù),返回一個輸入字符串的字節(jié)長度,其函數(shù)C語言的實(shí)現(xiàn)代碼如下: 在Python中的調(diào)用代碼如下: 其中,第33行使用c_char_p定義了一個指向char型的指針變量pStr,并賦初值為’abcdef’,第34行將其傳入GetStringLength函數(shù)返回其長度。 也可以使用下面代碼調(diào)用: 將GetStringLength函數(shù)的輸入輸出參數(shù)分別使用argtypes和restype單獨(dú)進(jìn)行聲明。 例2:如對于下面的函數(shù),輸入輸出皆為字符串指針,函數(shù)的功能是對于輸入pStr1賦值為“StrIn”,對于輸出返回一個指向字符串常量“strOut”的指針,其函數(shù)C語言的實(shí)現(xiàn)代碼如下: 在Python中的調(diào)用代碼如下: 在上面代碼中,同樣分別對輸入輸出參數(shù)進(jìn)行了聲明。對于輸入?yún)?shù)pStr,使用create_string_buffer函數(shù)定義了一個字符串緩沖區(qū)。對于返回值pChar,在打印輸出結(jié)果時,將其強(qiáng)制轉(zhuǎn)換為c_char_p類型,取其value值即可。 完整的測試代碼 完整的測試代碼如下圖所示: 運(yùn)行結(jié)果如下圖所示: 總結(jié) 這次的例子基本涵蓋了在Python中通過ctypes模塊調(diào)用DLL函數(shù)時,傳遞數(shù)值、指針、字符串類型參數(shù)時的大部分情況。要注意的是,使用ctypes映射C語言中的數(shù)據(jù)類型時,兩者必須完全一致。下面是Python的ctypes模塊中數(shù)據(jù)類型與C語言中數(shù)據(jù)類型對照表: |
|