久久r热视频,国产午夜精品一区二区三区视频,亚洲精品自拍偷拍,欧美日韩精品二区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

python使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)

瀏覽:110日期:2022-07-07 14:54:47

最近要使用python調(diào)用C++編譯生成的DLL動(dòng)態(tài)鏈接庫(kù),因此學(xué)習(xí)了一下ctypes庫(kù)的基本使用。

ctypes是一個(gè)用于Python的外部函數(shù)庫(kù),它提供C兼容的數(shù)據(jù)類型,并允許在DLL或共享庫(kù)中調(diào)用函數(shù)。

一、Python調(diào)用DLL里面的導(dǎo)出函數(shù)

1.VS生成dll

1.1 新建動(dòng)態(tài)鏈接庫(kù)項(xiàng)目

python使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)

1.2 在myTest.cpp中輸入以下內(nèi)容:

// myTest.cpp : 定義 DLL 應(yīng)用程序的導(dǎo)出函數(shù)。//#include 'stdafx.h'#define DLLEXPORT extern 'C' __declspec(dllexport) //放在 #include 'stdafx.h' 之后//兩數(shù)相加DLLEXPORT int sum(int a, int b) { return a + b;}

注意:導(dǎo)出函數(shù)前面要加 extern 'C' __declspec(dllexport) ,這是因?yàn)閏types只能調(diào)用C函數(shù)。如果不用extern 'C',構(gòu)建后的動(dòng)態(tài)鏈接庫(kù)沒有這些函數(shù)的符號(hào)表。采用C++的工程,導(dǎo)出的接口需要extern 'C',這樣python中才能識(shí)別導(dǎo)出的函數(shù)。

1.3生成dll動(dòng)態(tài)鏈接庫(kù)

因?yàn)槲业膒ython3是64位的,所以VS生成的dll要選擇64位的,如下所示:

python使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)

點(diǎn)擊標(biāo)題欄的 生成 -> 生成解決方案

python使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)

1.4 查看生成的dll動(dòng)態(tài)鏈接庫(kù)

python使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)

2.Python導(dǎo)入dll動(dòng)態(tài)鏈接庫(kù)

用python將動(dòng)態(tài)鏈接庫(kù)導(dǎo)入,然后調(diào)用動(dòng)態(tài)鏈接庫(kù)的函數(shù)。為此,新建main.py文件,輸入如下內(nèi)容:

from ctypes import *#----------以下四種加載DLL方式皆可—————————# pDLL = WinDLL('./myTest.dll')# pDll = windll.LoadLibrary('./myTest.dll')# pDll = cdll.LoadLibrary('./myTest.dll')pDll = CDLL('./myTest.dll')#調(diào)用動(dòng)態(tài)鏈接庫(kù)函數(shù)res = pDll.sum(1,2)#打印返回結(jié)果print(res)

運(yùn)行結(jié)果如下所示:

python使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)

二、Python調(diào)用DLL里面的實(shí)例方法更新全局變量值

1.VS生成dll

1.1 添加 mainClass 類,內(nèi)容如下:

mainClass.h:

#pragma onceextern int dta;class mainClass{public: mainClass(); ~mainClass(); void produceData();};

mainClass.cpp:

#include 'stdafx.h'#include 'mainClass.h'int dta = 0;mainClass::mainClass(){}mainClass::~mainClass(){}void mainClass::produceData() { dta = 10;}

1.2 更改 myTest.cpp 內(nèi)容

myTest.cpp:

#include 'stdafx.h'#define DLLEXPORT extern 'C' __declspec(dllexport) //放在 #include 'stdafx.h' 之后#include 'mainClass.h'//返回實(shí)例方法里面更新數(shù)據(jù)后的值DLLEXPORT int getRandData() { mainClass dataClass = mainClass(); dataClass.produceData(); return dta;}

1.3 生成64位dll

2.Python導(dǎo)入dll動(dòng)態(tài)鏈接庫(kù)

python使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)

明顯可以看出,在C++里設(shè)置的全局變量的值已經(jīng)從0變?yōu)?0了,說(shuō)明python可以通過(guò)調(diào)用dll里面的實(shí)例方法來(lái)更新全局變量值

三、Python_ctypes 指定函數(shù)參數(shù)類型和返回類型

前面兩個(gè)例子C++動(dòng)態(tài)鏈接庫(kù)導(dǎo)出函數(shù)的返回類型都是int型,而Python 默認(rèn)函數(shù)的參數(shù)類型和返回類型為 int 型,所以Python 理所當(dāng)然的 以為 dll導(dǎo)出函數(shù)返回了一個(gè) int 類型的值。但是如果C++動(dòng)態(tài)鏈接庫(kù)導(dǎo)出的函數(shù)返回類型不是int型,而是特定類型,就需要指定ctypes的函數(shù)返回類型 restype 。同樣,通過(guò)ctypes給函數(shù)傳遞參數(shù)時(shí),參數(shù)類型默認(rèn)為int型,如果不是int型,而是特定類型,就需要指定ctypes的函數(shù)形參類型 argtypes 。

接下來(lái),我將舉一個(gè)簡(jiǎn)單例子來(lái)說(shuō)明一下

myTest.cpp:

#include 'stdafx.h'#define DLLEXPORT extern 'C' __declspec(dllexport) //放在 #include 'stdafx.h' 之后#include <string> //使用string類型 需要包含頭文件 <string>using namespace std; //string類是一個(gè)模板類,位于名字空間std中//字符串DLLEXPORT char *getRandData(char *arg) { return arg;}

python代碼:

from ctypes import *pDll = CDLL('./myTest.dll')########## 指定 函數(shù)的參數(shù)類型 #################pDll.getRandData.argtypes = [c_char_p]#第一個(gè)參數(shù)arg1 = c_char_p(bytes('hello', ’utf-8’))########## 指定 函數(shù)的返回類型 #################pDll.getRandData.restype = c_char_p########### 調(diào)用動(dòng)態(tài)鏈接庫(kù)函數(shù) ##################res = pDll.getRandData(arg1)#打印返回結(jié)果print(res.decode()) #返回的是utf-8編碼的數(shù)據(jù),需要解碼

或者如下形式:

from ctypes import *pDll = CDLL('./myTest.dll')########## 指定 函數(shù)的返回類型 #################pDll.getRandData.restype = c_char_p########### 調(diào)用動(dòng)態(tài)鏈接庫(kù)函數(shù) ##################res = pDll.getRandData(b’hello’) # 或者變量.encode()#打印返回結(jié)果print(res.decode()) #返回的是utf-8編碼的數(shù)據(jù),需要解碼

運(yùn)行結(jié)果:

python使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)

四、Python_ctypes dll返回?cái)?shù)組_結(jié)構(gòu)體

在ctypes里,可以把數(shù)組指針傳遞給dll,但是我們無(wú)法通過(guò)dll獲取到c++返回的數(shù)組指針。由于python中沒有對(duì)應(yīng)的數(shù)組指針類型,因此,要獲取dll返回的數(shù)組,我們需要借助結(jié)構(gòu)體。

myTest.cpp:

#include 'stdafx.h'#define DLLEXPORT extern 'C' __declspec(dllexport) //放在 #include 'stdafx.h' 之后#include <string> //使用string類型 需要包含頭文件 <string>using namespace std; //string類是一個(gè)模板類,位于名字空間std中typedef struct StructPointerTest{ char name[20]; int age; int arr[3]; int arrTwo[2][3];}StructTest, *StructPointer;//sizeof(StructTest)就是求 struct StructPointerTest 這個(gè)結(jié)構(gòu)體占用的字節(jié)數(shù) //malloc(sizeof(StructTest))就是申請(qǐng) struct StructPointerTest 這個(gè)結(jié)構(gòu)體占用字節(jié)數(shù)大小的空間//(StructPointer)malloc(sizeof(StructTest))就是將申請(qǐng)的空間的地址強(qiáng)制轉(zhuǎn)化為 struct StructPointerTest * 指針類型//StructPointer p = (StructPointer)malloc(sizeof(StructTest))就是將那個(gè)強(qiáng)制轉(zhuǎn)化的地址賦值給 pStructPointer p = (StructPointer)malloc(sizeof(StructTest));//字符串DLLEXPORT StructPointer test() // 返回結(jié)構(gòu)體指針 { strcpy_s(p->name, 'Lakers'); p->age = 20; p->arr[0] = 3; p->arr[1] = 5; p->arr[2] = 10; for (int i = 0; i < 2; i++) for (int j = 0; j < 3; j++) p->arrTwo[i][j] = i*10+j; return p;}

python代碼:

# 返回結(jié)構(gòu)體import ctypespath = r’./myTest.dll’dll = ctypes.WinDLL(path)#定義結(jié)構(gòu)體class StructPointer(ctypes.Structure): #Structure在ctypes中是基于類的結(jié)構(gòu)體 _fields_ = [('name', ctypes.c_char * 20), #定義一維數(shù)組('age', ctypes.c_int),('arr', ctypes.c_int * 3), #定義一維數(shù)組('arrTwo', (ctypes.c_int * 3) * 2)] #定義二維數(shù)組#設(shè)置導(dǎo)出函數(shù)返回類型dll.test.restype = ctypes.POINTER(StructPointer) # POINTER(StructPointer)表示一個(gè)結(jié)構(gòu)體指針#調(diào)用導(dǎo)出函數(shù)p = dll.test()print(p.contents.name.decode()) #p.contents返回要指向點(diǎn)的對(duì)象 #返回的字符串是utf-8編碼的數(shù)據(jù),需要解碼print(p.contents.age)print(p.contents.arr[0]) #返回一維數(shù)組第一個(gè)元素print(p.contents.arr[:]) #返回一維數(shù)組所有元素print(p.contents.arrTwo[0][:]) #返回二維數(shù)組第一行所有元素print(p.contents.arrTwo[1][:]) #返回二維數(shù)組第二行所有元素

運(yùn)行結(jié)果:

python使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)

以上就是python使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)的詳細(xì)內(nèi)容,更多關(guān)于python 調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 威海市| 永丰县| 象州县| 岱山县| 丁青县| 白玉县| 繁峙县| 汾西县| 汤原县| 徐州市| 东阳市| 工布江达县| 衡山县| 府谷县| 永兴县| 渑池县| 平谷区| 利津县| 新民市| 保康县| 怀柔区| 孙吴县| 余江县| 阳新县| 渝北区| 滨州市| 新干县| 湛江市| 崇州市| 巴彦县| 望江县| 宁都县| 阿勒泰市| 涞水县| 永福县| 南涧| 台州市| 平江县| 自贡市| 左贡县| 镇坪县|