文章目录

  • 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 文件相关推荐

  1. python和C++联合开发(python调用DLL文件)

    在开发的过程中的有的厂家提供的API,或者其他同事写的功能模块用的是C++语言,而因为我们自己菜或者懒习惯使用python脚本语言开发,这里主要讲解如何使用python调用DLL文件(windows平 ...

  2. 【DLL】clion生成.dll文件、python调用.dll文件

    最近为了生成以及调用.dll文件,踩了一些雷,记录如下 目录 1.clion中生成.dll 2.clion中测试生成的.dll文件 3.在python中调用.dll文件 [1]导入.dll [2]ct ...

  3. python调用dll例子

    传字符串参数: def aaa(a):pStr = c_char_p( )pStr.value = areturn pStrparama= aaa(b"111.111.11.11" ...

  4. Python 调用 DLL

    Python 调用 DLL 一.C++ 编写 DLL 1..hpp 头文件 // dll_test.hpp#ifdef DLL_TEST #define MY_API _declspec(ddllex ...

  5. python编程(python调用dll程序)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 很多人说python的效率比较低,主要是没有分清什么时候用python.什么时候用c.对于网络. ...

  6. 用python读取身份证信息的功能分析与实现,兼述python调用dll的方法

    背景 有这样一个需求,要求能自动读取用户的身份证信息.如果是一代身份证,这个功能恐怕只能通过图像识别的办法来解决了.不过现在二代身份证已经很普及.客户要求能读二代身份证就可以了. 现在二代身份证阅读器 ...

  7. python调用dll函数指针_python使用ctypes库调用DLL动态链接库

    最近要使用python调用C++编译生成的DLL动态链接库,因此学习了一下ctypes库的基本使用. ctypes是一个用于Python的外部函数库,它提供C兼容的数据类型,并允许在DLL或共享库中调 ...

  8. 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 ...

  9. 关于java调用Dll文件的异常 %1 不是有效的 Win32 应用程序。

    关于java调用Dll文件的异常 %1 不是有效的 Win32 应用程序. 参考文章: (1)关于java调用Dll文件的异常 %1 不是有效的 Win32 应用程序. (2)https://www. ...

  10. python调用dll函数_从Python调用DLL函数

    我想从Python调用DLL中的函数.但我有个错误:"Attribute Error function not found" 这是我的代码:import os import cty ...

最新文章

  1. vue 不是内部或外部命令,也不是可运行的程序 或批处理文件
  2. AR(Augmented Reality)学习
  3. 轻松掌控全链路服务监控:方案概述与对比 | 真的很干!
  4. java频繁的new对象 优化方案
  5. SqlServer 索引
  6. Android监控wifi连接状态
  7. 何不用python_人生几何,何不Python当歌
  8. 最小二乘多项式拟合程序matlab,最小二乘法的多项式拟合(matlab实现)
  9. BeetleX之Websocket协议分析详解
  10. java学习(126):throw向上抛出异常
  11. windows xp 下的putty不能使用小键盘的问题
  12. dj电商-数据库的远程连接
  13. Bugfree 搭建
  14. 数据结构与算法-------希尔排序------交换法+移动法
  15. 上市也没打算盈利?Hadoop之父企业Cloudera好任性
  16. SpringCloud系列——Eureka中Region和Zone概念介绍
  17. Creator 3.0中摄像机调整技巧: 1.旋转:Cmd+右键 移动:空格+右键 放缩:滚轮
  18. Linux编程基础期末冲刺——第3章用户组与用户组管理
  19. 显卡驱动程序如何更新
  20. 视频教程-大数据技术-大数据

热门文章

  1. Nmap列举远程机器开放的端口
  2. 云服务器我的数据保存在哪个文件夹,云服务器存储在哪里
  3. 小程序 轮播图样式设置
  4. 下列选项中不是具体的python序列类型的是_以下选项中,不是具体的Python序列类型的是...
  5. nginx location正则匹配规则
  6. arm-linux驱动开发学习7
  7. Java案例:功夫熊猫
  8. Mysql中key 、primary key
  9. 电脑系统没有自带的字体-楷体GB2312字体 免费版提供下载
  10. 英飞凌TC297 PSPR与DSPR