python使用ctypes調(diào)用擴(kuò)展模塊的實(shí)例方法
楔子
我們知道python的執(zhí)行效率不是很高,而且由于GIL的原因,導(dǎo)致python不能充分利用多核CPU。一般的解決方式是使用多進(jìn)程,但是多進(jìn)程開(kāi)銷比較大,而且進(jìn)程之間的通信也會(huì)比較麻煩。因此在解決效率問(wèn)題上,我們會(huì)把那些比較耗時(shí)的模塊使用C或者C++編寫,然后編譯成動(dòng)態(tài)鏈接庫(kù),Windows上面是dll,linux上面則是so,編譯好之后,交給python去調(diào)用。而且通過(guò)擴(kuò)展模塊的方式還可以解決python的GIL的問(wèn)題,因此如果想要利用多核,我們?nèi)匀豢梢酝ㄟ^(guò)擴(kuò)展模塊的方式。
python如何調(diào)用擴(kuò)展模塊
python調(diào)用擴(kuò)展模塊的一種比較簡(jiǎn)單的方式就是使用ctypes這個(gè)庫(kù),這個(gè)庫(kù)是python官方提供的,任何一個(gè)版本的python都可以使用,我們通過(guò)ctypes可以很輕松地調(diào)用擴(kuò)展模塊。
演示
#include <stdio.h>
void test()
{
printf("hello world\n");
}
我們定義了一個(gè)很簡(jiǎn)單的函數(shù),下面我們就可以將其編譯成擴(kuò)展模塊了。在Windows是dll,linux上是so,編譯的命令是一樣的。我這里以Windows 為例,記得在Windows上要安裝MinGW,或者安裝VsCode,我這里使用的是MinGW,因?yàn)閂sCode太大了。
gcc -o dll文件或者so文件 -shared c或者c++源文件
我這里的C源文件叫做1.c,我們編譯成mmp.dll吧,所以命令就可以這么寫:gcc -o mmp.dll -shared 1.c

下面就可以使用python去調(diào)用了。
import ctypes
# 使用ctypes很簡(jiǎn)單,直接import進(jìn)來(lái),然后使用ctypes.CDLL這個(gè)類來(lái)加載動(dòng)態(tài)模塊
# 如果在Windows上還可以使用ctypes.WinDLL。
# 因?yàn)榭碿types源碼的話,會(huì)發(fā)現(xiàn)WinDLL也是一個(gè)類并且繼承自CDLL
# 所以在linux上使用ctypes.CDLL,
# 而在Windows上既可以使用WinDLL、也可以使用CDLL加載動(dòng)態(tài)模塊
lib = ctypes.CDLL("./mmp.dll") # 加載之后就得到了擴(kuò)展模塊
# 我們可以直接通過(guò).的方式去調(diào)用里面的函數(shù)了,會(huì)發(fā)現(xiàn)成功打印
lib.test() # hello world
# 但是為了確定是否存在這個(gè)函數(shù),我們一般會(huì)使用反射去獲取
# 因?yàn)槿绻瘮?shù)不存在通過(guò).的方式調(diào)用會(huì)拋異常的
func = getattr(lib, "test", None)
if func:
print(func) # <_FuncPtr object at 0x0000029F75F315F0>
func() # hello world
# 不存在test_xx這個(gè)函數(shù),所以得到的結(jié)果為None
func1 = getattr(lib, "test_xx", None)
print(func1) # None
所以使用ctypes去調(diào)用擴(kuò)展模塊非常方便
1.通過(guò)ctypes.CDLL("dll或者so的路徑"),如果是Windows還可以使用ctypes.WinDLL("dll路徑")。另外這兩種加載方式分別等價(jià)于:ctypes.CDLL("dll或者so的路徑") == ctypes.cdll.LoadLibrary("dll或者so的路徑"),ctypes.WinDLL("dll路徑") == ctypes.windll.LoadLibrary("dll路徑")。但是注意的是:linux上只能使用ctypes.CDLL和ctypes.cdll.LoadLibrary,而Windows上ctypes.CDLL、ctypes.cdll.LoadLibrary、ctypes.WinDLL、ctypes.windll.LoadLibrary都可以使用。但是一般我們都使用ctypes.CDLL即可,另外注意的是:dll或者so文件的路徑最好是絕對(duì)路徑,即便不是也要表明層級(jí),比如我們這里的py文件和dll文件是在同一個(gè)目錄下,但是我們加載的時(shí)候不可以寫mmp.dll,這樣會(huì)報(bào)錯(cuò)找不到,要寫成./mmp.dll。
2.加載動(dòng)態(tài)模塊之后會(huì)返回一個(gè)對(duì)象,我們上面起名為lib,這個(gè)lib就是得到的擴(kuò)展模塊了。
3.然后可以直接通過(guò)lib調(diào)用里面的函數(shù),但是一般我們會(huì)使用反射的方式來(lái)獲取,因?yàn)椴恢篮瘮?shù)到底存不存在,如果不存在直接調(diào)用會(huì)拋出異常,如果存在這個(gè)函數(shù)我們才會(huì)執(zhí)行。
以上就是本次介紹的全部相關(guān)知識(shí)點(diǎn),如果大家有任何補(bǔ)充的地方可以聯(lián)系腳本之家小編。
相關(guān)文章
Python中requests.session()的用法小結(jié)
這篇文章主要介紹了Python中requests.session()的用法小結(jié),可能大家對(duì)?session?已經(jīng)比較熟悉了,也大概了解了session的機(jī)制和原理,但是我們?cè)谧雠老x時(shí)如何會(huì)運(yùn)用到session呢,接下來(lái)要講到會(huì)話保持,需要的朋友可以參考下2022-11-11
Python 中的Schema數(shù)據(jù)結(jié)構(gòu)及類型校驗(yàn)詳解
schema?是一個(gè)簡(jiǎn)單而強(qiáng)大的庫(kù),用于定義和驗(yàn)證 Python 數(shù)據(jù)結(jié)構(gòu)的約束,使用?schema?庫(kù)來(lái)執(zhí)行數(shù)據(jù)結(jié)構(gòu)的校驗(yàn),本文給大家介紹Python 中的Schema數(shù)據(jù)結(jié)構(gòu)及類型校驗(yàn),感興趣的朋友一起看看吧2023-11-11
Python?flask框架post接口調(diào)用示例
這篇文章主要介紹了Python?flask框架post接口調(diào)用,結(jié)合實(shí)例形式分析了基于flask框架的post、get請(qǐng)求響應(yīng)及接口調(diào)用相關(guān)操作技巧,需要的朋友可以參考下2019-07-07
Python的網(wǎng)絡(luò)編程庫(kù)Gevent的安裝及使用技巧
Gevent庫(kù)的奧義在于并發(fā)式的高性能網(wǎng)絡(luò)程序設(shè)計(jì)支持,這里我們將來(lái)講解Python的網(wǎng)絡(luò)編程庫(kù)Gevent的安裝及使用技巧,來(lái)看一下Gevent支持的多進(jìn)程程序編寫:2016-06-06
python中g(shù)radio的輸出展示組件實(shí)例代碼
這篇文章主要介紹了python中g(shù)radio的輸出展示組件的相關(guān)資料,文章介紹了多種數(shù)據(jù)展示格式,包括HTML、JSON、KeyValues、Label、Markdown和Plot,每個(gè)格式都有其適用場(chǎng)景,需要的朋友可以參考下2024-11-11
Python利用PyPDF2庫(kù)合并多個(gè)pdf文件
PyPDF2庫(kù)是一個(gè)用于處理PDF文件的Python庫(kù),它提供了一系列的工具來(lái)讀取、編輯、合并、拆分和加密PDF文件,使得我們可以在Python環(huán)境下輕松地對(duì)PDF文件進(jìn)行操作,本文將帶大家介紹如何通過(guò)Python的PyPDF2庫(kù)合并多個(gè)pdf文件,需要的朋友可以參考下2023-05-05

