亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

python使用ctypes庫調(diào)用DLL動態(tài)鏈接庫

 更新時間:2020年10月22日 09:56:44   作者:蛋片雞  
這篇文章主要介紹了python如何使用ctypes庫調(diào)用DLL動態(tài)鏈接庫,幫助大家更好的理解和使用python,感興趣的朋友可以了解下

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

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

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

1.VS生成dll

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

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)建后的動態(tài)鏈接庫沒有這些函數(shù)的符號表。采用C++的工程,導(dǎo)出的接口需要extern "C",這樣python中才能識別導(dǎo)出的函數(shù)。

1.3生成dll動態(tài)鏈接庫

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

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

1.4 查看生成的dll動態(tài)鏈接庫

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

用python將動態(tài)鏈接庫導(dǎo)入,然后調(diào)用動態(tài)鏈接庫的函數(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)用動態(tài)鏈接庫函數(shù)
res = pDll.sum(1,2)
#打印返回結(jié)果
print(res)

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

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

1.VS生成dll

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

mainClass.h:

#pragma once

extern 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動態(tài)鏈接庫

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

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

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

接下來,我將舉一個簡單例子來說明一下

myTest.cpp:

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

python代碼:

from ctypes import *
pDll = CDLL("./myTest.dll")

########## 指定 函數(shù)的參數(shù)類型 #################
pDll.getRandData.argtypes = [c_char_p]
#第一個參數(shù)
arg1 = c_char_p(bytes("hello", 'utf-8'))

########## 指定 函數(shù)的返回類型 #################
pDll.getRandData.restype = c_char_p

########### 調(diào)用動態(tài)鏈接庫函數(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)用動態(tài)鏈接庫函數(shù) ##################
res = pDll.getRandData(b'hello') # 或者變量.encode()

#打印返回結(jié)果
print(res.decode()) #返回的是utf-8編碼的數(shù)據(jù),需要解碼

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

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

在ctypes里,可以把數(shù)組指針傳遞給dll,但是我們無法通過dll獲取到c++返回的數(shù)組指針。由于python中沒有對應(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類是一個模板類,位于名字空間std中


typedef struct StructPointerTest
{
  char name[20];
  int age;
  int arr[3];
  int arrTwo[2][3];
}StructTest, *StructPointer;


//sizeof(StructTest)就是求 struct StructPointerTest 這個結(jié)構(gòu)體占用的字節(jié)數(shù) 
//malloc(sizeof(StructTest))就是申請 struct StructPointerTest 這個結(jié)構(gòu)體占用字節(jié)數(shù)大小的空間
//(StructPointer)malloc(sizeof(StructTest))就是將申請的空間的地址強(qiáng)制轉(zhuǎn)化為 struct StructPointerTest * 指針類型
//StructPointer p = (StructPointer)malloc(sizeof(StructTest))就是將那個強(qiáng)制轉(zhuǎn)化的地址賦值給 p
StructPointer 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 ctypes

path = 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)表示一個結(jié)構(gòu)體指針
#調(diào)用導(dǎo)出函數(shù)
p = dll.test()

print(p.contents.name.decode()) #p.contents返回要指向點(diǎn)的對象  #返回的字符串是utf-8編碼的數(shù)據(jù),需要解碼
print(p.contents.age)
print(p.contents.arr[0]) #返回一維數(shù)組第一個元素
print(p.contents.arr[:]) #返回一維數(shù)組所有元素
print(p.contents.arrTwo[0][:]) #返回二維數(shù)組第一行所有元素
print(p.contents.arrTwo[1][:]) #返回二維數(shù)組第二行所有元素

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

以上就是python使用ctypes庫調(diào)用DLL動態(tài)鏈接庫的詳細(xì)內(nèi)容,更多關(guān)于python 調(diào)用DLL動態(tài)鏈接庫的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • PyTorch中Torch.arange函數(shù)詳解

    PyTorch中Torch.arange函數(shù)詳解

    PyTorch是由Facebook開發(fā)的開源機(jī)器學(xué)習(xí)庫,它用于深度神經(jīng)網(wǎng)絡(luò)和自然語言處理,下面這篇文章主要給大家介紹了關(guān)于PyTorch中Torch.arange函數(shù)詳解的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • Python中執(zhí)行JavaScript實(shí)現(xiàn)數(shù)據(jù)抓取的多種方法

    Python中執(zhí)行JavaScript實(shí)現(xiàn)數(shù)據(jù)抓取的多種方法

    JavaScript是一門強(qiáng)大的腳本語言,廣泛應(yīng)用于網(wǎng)頁前端開發(fā)、構(gòu)建交互式用戶界面以及處理各種客戶端端任務(wù),有時可能需要在Python環(huán)境中執(zhí)行JavaScript代碼,本文將介紹多種方法,幫助你在Python中執(zhí)行 JavaScript代碼,并提供詳盡的示例代碼,使你能夠輕松掌握這一技能
    2023-11-11
  • Django配置跨域并開發(fā)測試接口

    Django配置跨域并開發(fā)測試接口

    這篇文章主要介紹了Django配置跨域并開發(fā)測試接口,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • Python使用函數(shù)輔助工具簡化開發(fā)提高效率

    Python使用函數(shù)輔助工具簡化開發(fā)提高效率

    這篇文章主要為大家介紹了Python使用函數(shù)輔助工具簡化開發(fā)提高效率,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Python中單引號、雙引號和三引號具體的用法及注意點(diǎn)

    Python中單引號、雙引號和三引號具體的用法及注意點(diǎn)

    這篇文章主要給大家介紹了關(guān)于Python中單引號、雙引號和三引號具體的用法及注意點(diǎn)的相關(guān)資料,Python中單引號、雙引號、三引號中使用常常困惑,想弄明白這三者相同點(diǎn)和不同點(diǎn),需要的朋友可以參考下
    2023-07-07
  • Python定義函數(shù)實(shí)現(xiàn)累計(jì)求和操作

    Python定義函數(shù)實(shí)現(xiàn)累計(jì)求和操作

    這篇文章主要介紹了Python定義函數(shù)實(shí)現(xiàn)累計(jì)求和操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05
  • opencv對多種顏色小球的形狀及位置判斷方式

    opencv對多種顏色小球的形狀及位置判斷方式

    在這段時間參加了一個競賽,寫下了這個代碼,但是總感覺有一些地方是不完善!這是一個關(guān)于使用opencv庫判斷顏色小球形狀及位置的功能實(shí)現(xiàn),其中也參考了一些前輩的代碼,希望能對迷茫中的小伙幫有所幫助
    2022-11-11
  • python3中join和格式化的用法小結(jié)

    python3中join和格式化的用法小結(jié)

    這篇文章主要介紹了python中os庫的使用,本篇文章記錄下python中os庫的一些函數(shù)使用,對python?os庫使用感興趣的朋友跟隨小編一起看看吧
    2022-10-10
  • Python 常見加密操作的實(shí)現(xiàn)

    Python 常見加密操作的實(shí)現(xiàn)

    這篇文章主要介紹了Python 常見加密操作的實(shí)現(xiàn),幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下
    2021-03-03
  • python實(shí)現(xiàn)TCP文件傳輸

    python實(shí)現(xiàn)TCP文件傳輸

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)TCP文件傳輸,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03

最新評論