Python调用 dll 文件
文章目录
- DLL 样例
- 调用方法
- 带结构体
- 进阶: `回调函数, 类型指针, 传递python类型`
- 更进阶: `ctypes 改写获取到的指针所指向的内容`
- 注意
DLL 样例
- VC 编译器
// func.c
#ifdef _MSC_VER#define DLL_EXPORT __declspec( dllexport )
#else#define DLL_EXPORT
#endifDLL_EXPORT int add(int a,int b)
{return a+b;
}DLL_EXPORT void print_s(const char* s)
{printf("Hello %s", s);
}
编译:cl /LD func.c /o func.dll
- gcc 编译器
// func.c
int add(int a,int b)
{return a+b;
}void update(double a[], int size)
{for (int i = 0; i < size; i++)*a++ *= 0.0098;
}void print_s(const char* s)
{printf("Hello %s", s);
}
编译:gcc func.c -shared -o func.dll
调用方法
from ctypes import *dll = CDLL("func.dll")
dll.add(23, 33)
length = dll.print_s(c_char_p(b"Andy"))
print(length)arr = (c_double*5)()
arr[0] = 100
arr[1] = 200
arr[2] = 300
arr[3] = 200
arr[4] = 200
dll.update(byref(arr), len(arr))for item in arr:print(item)
out:
56
Hello Andy
10
0.98
1.96
2.94
1.96
1.96
带结构体
// func.c
// 如果 dll 文件中的函数用到了 C 结构体,比如
struct Header { unsigned short Version; char Manufacturer[16]; char Type[16]; unsigned int Timestamp; unsigned int _; unsigned short TaskID;
};int r_header(struct Header *header, char *binfile);
# python
from ctypes import *class Header(Structure): # 继承 Structure 类_fields_ = [("ver", c_ushort),("manuf", (c_char*16)),("typ", (c_char*16)),("ts", c_uint),("_", c_uint),("tid", c_ushort)]rbs = CDLL("func.dll")
h = Header() # 声明一个python 版的结构体
rbs.r_header.restype = c_int # 指定 dll 内函数 r_header 返回类型
code = rbs.r_header(byref(h), c_char_p(b"./binfile.bin")) # 传入 h 地址,会被写入读取到的值
if code != 0:print("error")print(h.ver, h.manuf, h.typ, h.ts, h.tid)
进阶: 回调函数, 类型指针, 传递python类型
将 python 函数做为回调函数传给dll
// func.h// 数据结构体
typedef struct Data {int Msec;long long Timestamp;double Volume;double Amount;
} Data;// 回调函数签名
typedef void(*cb) (void* arr, const Data* d, void* opt);/*
* 生成 Data 数据, 传给回调函数
* @param: func 回调函数
* @param: arr 任意指针, 将传递给回调函数
* @param: opt 任意指针, 将传递给回调函数
*/
void create_data(cb func, void* arr, void* opt);
// func.c
#include "func.h"void create_data(cb func, void* arr, void* opt)
{Data d {500, 1601548587, 55555, 88888888};func(arr, &d, opt);
}
# test.py
from ctypes import *
from copy import deepcopyclass Data(Structure):_fields_ = [("Msec", c_int),("Timestamp", c_int64),("Volume", c_double),("Amount", c_double)]
class Param(Structure):_fields_ = [("x", c_int),("y", c_int)]
# 定义 python 回调函数, 用来被 createData() 调用, 接收 Data 数据
# @param: pyList python 列表
# @param: data Data 结构体指针
# @param: opt 其他参数
def callback(pyList: list, data: POINTER(Data), opt: c_void_p):p = cast(opt, POINTER(Param))[0] # 指针类型转换print(p.x, p.y)pyList.append(deepcopy(data[0])) # 拷贝指针指向内容# 定义回调函数签名, 第一个参数是指代函数返回值, 后面三个才是实参
funcType = CFUNCTYPE(None, py_object, POINTER(Data), c_void_p)
cb = funcType(callback) # 实例化mydll = CDLL("func.dll")
dataArr = [] # 用来保存 Data 数据
para = Param()
para.x = 11
para.y = 22
mydll.create_data(cb, c_void_p(id(dataArr), byref(para))
# 输出结果
for item in dataArr:print(item.Msec, item.Timestamp, item.Volume, item.Amount)
更进阶: ctypes 改写获取到的指针所指向的内容
// func.h//该回调函数向 buff 写入字符串
typedef void(*write_buff) (char* buff);/*
* 处理由回调函数产生的字符串
* @param: f 回调函数
*/
void print_something(write_buff f);
// func.c
#include "func.h"void print_something(write_buff f)
{char buff[32]; // 字符数组作为buffer 接收字符串f(buff); // 执行回调函数, 取得字符printf("get str: [%s]", buff); // python调用可能不会打印出来, buff 内容确实被回调函数修改了
}
# test.py
from ctypes import *
import time# 定义 python 回调函数, 用来被 print_something() 调用, 生成字符串
# @param: buff c_char 指针
def new_str(buff: POINTER(c_char)):dt = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) # 当前日期时间字符串memmove(buff, dt.encode(), len(dt)) # 拷贝 dt 字符到 buff 中, 这个 buff 空间是在 dll 中开辟的funcType = CFUNCTYPE(None, POINTER(c_char))
cb = funcType(new_str) # 实例化mydll = CDLL("func.dll")
mydll.print_something(cb)
#> get str: [2022-03-16 15:13:00]
注意
一定要注意你用的Python 是多少位的(32/64位),还有你使用的编译器是多少位的,一定要对应。
否则会报错:不是有效的32位程序
,32位 python 用不了64位的 dll, 64位 python 也用不了32 位的dll
我就被这个折腾了好久
Python调用 dll 文件相关推荐
- python和C++联合开发(python调用DLL文件)
在开发的过程中的有的厂家提供的API,或者其他同事写的功能模块用的是C++语言,而因为我们自己菜或者懒习惯使用python脚本语言开发,这里主要讲解如何使用python调用DLL文件(windows平 ...
- 【DLL】clion生成.dll文件、python调用.dll文件
最近为了生成以及调用.dll文件,踩了一些雷,记录如下 目录 1.clion中生成.dll 2.clion中测试生成的.dll文件 3.在python中调用.dll文件 [1]导入.dll [2]ct ...
- python调用dll例子
传字符串参数: def aaa(a):pStr = c_char_p( )pStr.value = areturn pStrparama= aaa(b"111.111.11.11" ...
- Python 调用 DLL
Python 调用 DLL 一.C++ 编写 DLL 1..hpp 头文件 // dll_test.hpp#ifdef DLL_TEST #define MY_API _declspec(ddllex ...
- python编程(python调用dll程序)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 很多人说python的效率比较低,主要是没有分清什么时候用python.什么时候用c.对于网络. ...
- 用python读取身份证信息的功能分析与实现,兼述python调用dll的方法
背景 有这样一个需求,要求能自动读取用户的身份证信息.如果是一代身份证,这个功能恐怕只能通过图像识别的办法来解决了.不过现在二代身份证已经很普及.客户要求能读二代身份证就可以了. 现在二代身份证阅读器 ...
- python调用dll函数指针_python使用ctypes库调用DLL动态链接库
最近要使用python调用C++编译生成的DLL动态链接库,因此学习了一下ctypes库的基本使用. ctypes是一个用于Python的外部函数库,它提供C兼容的数据类型,并允许在DLL或共享库中调 ...
- python调用dll报错:ValueError: Procedure called with not enough arguments (4 bytes missing) or wrong call
python调用dll报错:ValueError: Procedure called with not enough arguments (4 bytes missing) or wrong call ...
- 关于java调用Dll文件的异常 %1 不是有效的 Win32 应用程序。
关于java调用Dll文件的异常 %1 不是有效的 Win32 应用程序. 参考文章: (1)关于java调用Dll文件的异常 %1 不是有效的 Win32 应用程序. (2)https://www. ...
- python调用dll函数_从Python调用DLL函数
我想从Python调用DLL中的函数.但我有个错误:"Attribute Error function not found" 这是我的代码:import os import cty ...
最新文章
- vue 不是内部或外部命令,也不是可运行的程序 或批处理文件
- AR(Augmented Reality)学习
- 轻松掌控全链路服务监控:方案概述与对比 | 真的很干!
- java频繁的new对象 优化方案
- SqlServer 索引
- Android监控wifi连接状态
- 何不用python_人生几何,何不Python当歌
- 最小二乘多项式拟合程序matlab,最小二乘法的多项式拟合(matlab实现)
- BeetleX之Websocket协议分析详解
- java学习(126):throw向上抛出异常
- windows xp 下的putty不能使用小键盘的问题
- dj电商-数据库的远程连接
- Bugfree 搭建
- 数据结构与算法-------希尔排序------交换法+移动法
- 上市也没打算盈利?Hadoop之父企业Cloudera好任性
- SpringCloud系列——Eureka中Region和Zone概念介绍
- Creator 3.0中摄像机调整技巧: 1.旋转:Cmd+右键 移动:空格+右键 放缩:滚轮
- Linux编程基础期末冲刺——第3章用户组与用户组管理
- 显卡驱动程序如何更新
- 视频教程-大数据技术-大数据