python库_python使用ctypes库调用DLL动态链接库_python
最近要使用python調用C++編譯生成的DLL動態鏈接庫,因此學習了一下ctypes庫的基本使用。
ctypes是一個用于Python的外部函數庫,它提供C兼容的數據類型,并允許在DLL或共享庫中調用函數。
一、Python調用DLL里面的導出函數
生成dll
1.1 新建動態鏈接庫項目
在中輸入以下內容:
// : 定義 DLL 應用程序的導出函數。 // #include "" #define DLLEXPORT extern "C" __declspec(dllexport) //放在 #include "" 之后 //兩數相加 DLLEXPORT int sum(int a, int b) {return a + b; }注意:導出函數前面要加??extern "C" __declspec(dllexport) ,這是因為ctypes只能調用C函數。如果不用extern "C",構建后的動態鏈接庫沒有這些函數的符號表。采用C++的工程,導出的接口需要extern "C",這樣python中才能識別導出的函數。
生成dll動態鏈接庫
因為我的python3是64位的,所以VS生成的dll要選擇64位的,如下所示:
點擊標題欄的 生成 -> 生成解決方案?
查看生成的dll動態鏈接庫
導入dll動態鏈接庫
用python將動態鏈接庫導入,然后調用動態鏈接庫的函數。為此,新建文件,輸入如下內容:
from ctypes import *#----------以下四種加載DLL方式皆可————————— # pDLL = WinDLL("./") # pDll = ("./") # pDll = ("./") pDll = CDLL("./")#調用動態鏈接庫函數 res = (1,2) #打印返回結果 print(res)運行結果如下所示:
二、Python調用DLL里面的實例方法更新全局變量值
生成dll
1.1 添加 mainClass 類,內容如下:
:
#pragma onceextern int dta; class mainClass { public:mainClass();~mainClass();void produceData(); };:
#include "" #include ""int dta = 0;mainClass::mainClass() { }mainClass::~mainClass() { }void mainClass::produceData() {dta = 10; }更改 內容
:
#include "" #define DLLEXPORT extern "C" __declspec(dllexport) //放在 #include "" 之后 #include ""//返回實例方法里面更新數據后的值 DLLEXPORT int getRandData() {mainClass dataClass = mainClass();();return dta; }生成64位dll
導入dll動態鏈接庫
明顯可以看出,在C++里設置的全局變量的值已經從0變為10了,說明python可以通過調用dll里面的實例方法來更新全局變量值
三、Python_ctypes 指定函數參數類型和返回類型
前面兩個例子C++動態鏈接庫導出函數的返回類型都是int型,而Python 默認函數的參數類型和返回類型為 int 型,所以Python?理所當然的 以為 dll導出函數返回了一個 int 類型的值。但是如果C++動態鏈接庫導出的函數返回類型不是int型,而是特定類型,就需要指定ctypes的函數返回類型 restype 。同樣,通過ctypes給函數傳遞參數時,參數類型默認為int型,如果不是int型,而是特定類型,就需要指定ctypes的函數形參類型?argtypes 。
接下來,我將舉一個簡單例子來說明一下
:
#include "" #define DLLEXPORT extern "C" __declspec(dllexport) //放在 #include "" 之后 #include <string> //使用string類型 需要包含頭文件 <string> using namespace std; //string類是一個模板類,位于名字空間std中 //字符串 DLLEXPORT char *getRandData(char *arg) {return arg; }python代碼:
from ctypes import * pDll = CDLL("./")########## 指定 函數的參數類型 ################# .argtypes = [c_char_p] #第一個參數 arg1 = c_char_p(bytes("hello", 'utf-8'))########## 指定 函數的返回類型 ################# .restype = c_char_p########### 調用動態鏈接庫函數 ################## res = (arg1)#打印返回結果 print(()) #返回的是utf-8編碼的數據,需要解碼或者如下形式:
from ctypes import * pDll = CDLL("./")########## 指定 函數的返回類型 ################# .restype = c_char_p########### 調用動態鏈接庫函數 ################## res = (b'hello') # 或者變量.encode()#打印返回結果 print(()) #返回的是utf-8編碼的數據,需要解碼運行結果:
四、Python_ctypes dll返回數組_結構體
在ctypes里,可以把數組指針傳遞給dll,但是我們無法通過dll獲取到c++返回的數組指針。由于python中沒有對應的數組指針類型,因此,要獲取dll返回的數組,我們需要借助結構體。
?:
#include "" #define DLLEXPORT extern "C" __declspec(dllexport) //放在 #include "" 之后 #include <string> //使用string類型 需要包含頭文件 <string> using namespace std; //string類是一個模板類,位于名字空間std中typedef struct StructPointerTest {char name[20];int age;int arr[3];int arrTwo[2][3]; }StructTest, *StructPointer;//sizeof(StructTest)就是求 struct StructPointerTest 這個結構體占用的字節數 //malloc(sizeof(StructTest))就是申請 struct StructPointerTest 這個結構體占用字節數大小的空間 //(StructPointer)malloc(sizeof(StructTest))就是將申請的空間的地址強制轉化為 struct StructPointerTest * 指針類型 //StructPointer p = (StructPointer)malloc(sizeof(StructTest))就是將那個強制轉化的地址賦值給 p StructPointer p = (StructPointer)malloc(sizeof(StructTest));//字符串 DLLEXPORT StructPointer test() // 返回結構體指針 {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代碼:
# 返回結構體 import ctypespath = r'./' dll = (path)#定義結構體 class StructPointer(): #Structure在ctypes中是基于類的結構體_fields_ = [("name", * 20), #定義一維數組("age", ),("arr", * 3), #定義一維數組("arrTwo", ( * 3) * 2)] #定義二維數組#設置導出函數返回類型 .restype = ctypes.POINTER(StructPointer) # POINTER(StructPointer)表示一個結構體指針 #調用導出函數 p = ()print(()) #返回要指向點的對象 #返回的字符串是utf-8編碼的數據,需要解碼 print(.age) print(.arr[0]) #返回一維數組第一個元素 print(.arr[:]) #返回一維數組所有元素 print(.arrTwo[0][:]) #返回二維數組第一行所有元素 print(.arrTwo[1][:]) #返回二維數組第二行所有元素運行結果:
以上就是python使用ctypes庫調用DLL動態鏈接庫的詳細內容,更多關于python 調用DLL動態鏈接庫的資料請關注腳本之家其它相關文章!
總結
以上是生活随笔為你收集整理的python库_python使用ctypes库调用DLL动态链接库_python的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BugkuCTF-Misc:隐写3
- 下一篇: BugkuCTF-Misc:做个游戏(0