【Python】Windows平台调用DLL中的方法

简介: 一、前言 我有一次在用Python开发项目工具的时候,需要用到一个加解密的模块。但是这个模块是纯C实现的,而且也是项目自己实现的算法,不可能有现成的Python库可以使用,当然我也不能用Python再写一遍。因此就想用Python调用C的接口,通过面向搜索引擎编程,找到了Python可以使用ctypes调用dll的方法,经过一番折腾后成功搞定。本篇文章特此记录一下之前学习的内容。

【Python】Windows平台调用DLL中的方法


一、前言


       我有一次在用Python开发项目工具的时候,需要用到一个加解密的模块。但是这个模块是纯C实现的,而且也是项目自己实现的算法,不可能有现成的Python库可以使用,当然我也不能用Python再写一遍。因此就想用Python调用C的接口,通过面向搜索引擎编程,找到了Python可以使用ctypes调用dll的方法,经过一番折腾后成功搞定。本篇文章特此记录一下之前学习的内容。


640.png


二、开始


       首先需要有一个DLL文件,如名为encrypt.dll的DLL文件,里面包含的接口定义在下面。然后我们开始一步步完成加载dll文件,并调用其中的方法。


// 创建一个加密解密对象, 通过传入的密钥
encrypt_obj* create(int key);
// 使用加密对象进行加密文本
void do_encrypt(encrypt_obj* obj, char* text, int size);
// 使用解密对象进行解密
void do_decrypt(encrypt_obj* obj, char* btext, int size);


   1. 加载dll


   一个简单的加载dll的代码如下:


import ctypes
encrypt_dll = ctypes.CDLL("encrypt.dll")


   我们知道dll的接口有stdcallcdecl两种调用约定,因此ctypes加载dll也有两种方式:


# stdcall
std_dll = ctypes.windll.LoadLibrary("dll")
std_dll = ctypes.WinDLL("dll")
# cdecl
cd_dll = ctypes.cdll.LoadLibrary("dll")
cd_dll = ctypes.CDLL("dll")
 
2.调用传参


   完成第一步的dll加载后,会返回这个dll的对象,现在我们就可以调用里面的方法了,例如:encrypt_dll.create(1)


   调用方法参数传递时,分基本类型和指针类型。基本的类型例如: int、float、char、short 这些都可以直接调用传入参数。但如果是指针类型,例如int*,就需要做一下转化,具体如下:


# 先创建一个int的对象
int_v = ctypes.c_int(1)
# 然后调用byref 作为指针传入方法中
dll.func(ctypes.byref(int_v))


   另外参数为char* 时,调用的代码如下:


# 1. 创建字符串
pstr = ctypes.c_char_p("string text")
# 或者
pstr = ctypes.c_char_p()
pstr.value = "string text"
# 2.然后调用传参
dll.func(ctypes.byref(pstr))


   如果既需要传入参数,也需要获取方法执行的返回值,而且不想像上面那样进行几步操作的话,可以使用下面的方式。在一开始就显示的定义好dll中的每个方法的传入参数类型,返回参数类型。这样就可以更方便的进行方法调用了。


# 先声明dll的这个方法的传入参数和返回值类型
encrypt_dll.create.argtypes = [c_int]
encrypt_dll.create.restypes = c_void_p
# 这样就可以直接调用
obj = encrypt_dll.create(1)
# 只定义传入参数类型,不定义返回值类型
encrypt_dll.do_encrypt.argtypes=[c_void_p,c_char_p,c_int]
# 定义好参数类型后,就可以直接传入参数了。
encrypt_dll.do_encrypt(obj, "aaa", 3)


   3. C基本类型和ctypes中类型映射表


c_char
char
c_short
short
c_int
int
c_long
long
c_ulong
unsigned long
c_float
float
c_double
double
c_void_p
void*


   针对表格前面7个,如果是指针类型时,就是在对应的类型后面加上"_p"。例如char* 就是c_char_p, int* 就是 c_int_p 等。


   4. 处理结构体


   如果有时候需要使用C的结构体,例如做一些赋值,读取数据的操作,这个时候就需要在Python中定义一个C的结构体类。以下是简单的一个例子。


// C语言中的结构体
typedef struct _myStruct
{
    int nValue;
    char szBuffer[128];
} MyStruct;


# Python中实现
import ctypes
class MyStruct(ctypes.Structure):
""" 继承自Structure """
  _fields_ = [
    ("nValue", ctypes.c_int),
    ("szBuffer", ctypes.c_char * 128)]
# 调用方式如下
dll = ctypes.CDLL("sample.dll")
my = MyStruct()
my.nValue = 123123
my.szBuffer = "string text"
dll.callfunc(ctypes.byref(my))


三、总结


   以上就是Python中调用Windows中的dll的方法,根据上面的方法我们就可以与C进行交互了,是不是很简单呢?希望看后对大家有帮助!


欢迎微信搜索"游戏测试开发"关注一起沟通交流。

相关文章
|
2天前
|
存储 Linux Shell
python移除/删除非空文件夹/目录的最有效方法是什么?
python移除/删除非空文件夹/目录的最有效方法是什么?
8 0
|
5天前
|
Python
【Python 基础】Python中的实例方法、静态方法和类方法有什么区别?
【5月更文挑战第6天】【Python 基础】Python中的实例方法、静态方法和类方法有什么区别?
|
5天前
|
数据处理 Python
Python中每个字段增加多条数据的高效方法
Python中每个字段增加多条数据的高效方法
10 1
|
5天前
|
存储 数据挖掘 Python
Python技术分享:实现选择文件或目录路径的方法
Python技术分享:实现选择文件或目录路径的方法
15 2
|
5天前
|
数据处理 Python
Python中按指定数量分割列表字符串的方法
Python中按指定数量分割列表字符串的方法
9 1
|
9天前
|
Windows
Windows 程序自启动实现方法详解
Windows 程序自启动实现方法详解
25 0
|
9天前
|
Python
使用Python pandas的sort_values()方法可按一个或多个列对DataFrame排序
使用Python pandas的sort_values()方法可按一个或多个列对DataFrame排序。示例代码展示了如何按'Name'和'Age'列排序 DataFrame。先按'Name'排序,再按'Age'排序。sort_values()的by参数接受列名列表,ascending参数控制排序顺序(默认升序),inplace参数决定是否直接修改原DataFrame。
23 1
|
11天前
|
机器学习/深度学习 数据可视化 前端开发
【Python机器学习专栏】机器学习模型评估的实用方法
【4月更文挑战第30天】本文介绍了机器学习模型评估的关键方法,包括评估指标(如准确率、精确率、召回率、F1分数、MSE、RMSE、MAE及ROC曲线)和交叉验证技术(如K折交叉验证、留一交叉验证、自助法)。混淆矩阵提供了一种可视化分类模型性能的方式,而Python的scikit-learn库则方便实现这些评估。选择适合的指标和验证方法能有效优化模型性能。
|
11天前
|
机器学习/深度学习 算法 Python
【Python机器学习专栏】Python中的特征选择方法
【4月更文挑战第30天】本文介绍了机器学习中特征选择的重要性,包括提高模型性能、减少计算成本和增强可解释性。特征选择方法主要包括过滤法(如相关系数、卡方检验和互信息)、包装法(如递归特征消除和顺序特征选择)和嵌入法(如L1正则化和决策树)。在Python中,可利用`sklearn`库的`feature_selection`模块实现这些方法。通过有效的特征选择,能构建更优的模型并深入理解数据。
|
11天前
|
机器学习/深度学习 数据采集 数据可视化
【Python 机器学习专栏】数据缺失值处理与插补方法
【4月更文挑战第30天】本文探讨了Python中处理数据缺失值的方法。缺失值影响数据分析和模型训练,可能导致模型偏差、准确性降低和干扰分析。检测缺失值可使用Pandas的`isnull()`和`notnull()`,或通过可视化。处理方法包括删除含缺失值的行/列及填充:固定值、均值/中位数、众数或最近邻。Scikit-learn提供了SimpleImputer和IterativeImputer类进行插补。选择方法要考虑数据特点、缺失值比例和模型需求。注意过度插补和验证评估。处理缺失值是提升数据质量和模型准确性关键步骤。