利用Pybind11封装Python版的WiringPi!

news2025/1/16 16:00:15

原版的WiringPi是一个用于树莓派的GPIO库,用C语言开发,仓库地址:https://github.com/WiringPi/WiringPi。该库允许用户以编程方式访问和控制树莓派的GPIO引脚。而随着Python在嵌入式设备上的快速发展,其对底层引脚的操作也变得越来越多,因此将WiringPi中的API接口封装出对应的Python接口显得格外重要了。

目前是有这个库的Python版本:https://github.com/WiringPi/WiringPi-Python,是利用swig这个工具自动读取头文件完成相关接口的封装,但该方式从使用角度来看存在以下几点问题:

  • 灵活性不够强。比如:某些函数返回值通过输入的指针来传递,这种swig就没法有效识别。
  • 未封装注释,且开发时无法弹出其中的API。开发时无法知道so文件内有什么函数,只能通过尝试去找相关用法。
  • 存在重定义问题。WiringPi是C语言,部分头文件存在重定义问题。

Python的最大优势就是降低开发者的使用难度,因此上述这个仓库并未良好的展示出这一特点。考虑到Pybind11是一款广为使用的封装工具,熟知的pytorch就是基于这个工具将其C++接口封装为python的。因此,我就借用Pybind11来提供一个超好用的Python版的WiringPi!!!!

🌈仓库地址:https://github.com/Li-Zhaoxi/Pybind11-WiringPi

下面将介绍怎么安装编译Python版的WiringPi,并介绍了使用方法,以及这段时间的开发历程。

💡💡特别感谢晟哥在使用体验上提供的宝贵建议😎😎

文章目录

  • 一 工具包编译
  • 二 使用方式
  • 三 开发过程
  • 四 小结

一 工具包编译

在编译前,有以下几点需要注意下:

  • 目前封装的WiringPi的仓库地址是https://gitee.com/study-dp/WiringPi,仅适用于地平线开发板。其他开发板比如树莓派等,我手上暂时没有,在后续开发中会慢慢补上,各位可以多多关注仓库主页以及Release信息。
  • Python包依赖C++库,编译时候会安装到系统环境中。在之后迭代时我打算将编译出的so文件都放在包这个路径下,而且编译过程全部自动化处理。

我说下封装的思想,Python包是在现有C++动态库的基础上进行的二次封装,这样在C++项目中和Python项目中只会启动一个so文件,起到节省内存的作用。

  • 如果你想从头编译本项目,编译安装流程如下:
# 安装依赖包
sudo pip3 install mypy ninja

# 下载项目,recursive必须要加
git clone --recursive https://github.com/Li-Zhaoxi/Pybind11-WiringPi
cd Pybind11-WiringPi

# 安装依赖的WiringPi C动态库
cd 3rdparty/WiringPi-RDK
./build
cd ../..

# 安装Pybind11
cd 3rdparty/pybind11
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF ..
sudo make install
cd ../../..

# 编译出用于安装的python.whl
python3 setup.py bdist_wheel

# 安装我们编译好的包
sudo pip3 install dist/WiringPi*.whl
  • 如果你想利用我编译好的whl文件,可以从这里下载编译好的whl文件WiringPi-0.1.0-cp38-cp38-linux_aarch64.whl,之后编译安装流程如下:
# 下载项目,recursive必须要加
git clone --recursive https://github.com/Li-Zhaoxi/Pybind11-WiringPi
cd Pybind11-WiringPi

# 安装依赖的WiringPi C动态库
cd 3rdparty/WiringPi-RDK
./build
cd ../..

# 安装提供的python包,<path>表示包存放的根目录
sudo pip3 install <path>/WiringPi-0.1.0-cp38-cp38-linux_aarch64.whl

输入python3,如果能正确import WiringPi,就表明你已经正确安装当前项目,可以快乐开发了。

二 使用方式

先放使用效果图,在import WiringPi之后,你可以直接看到包内的所有函数接口以及相关的注释每个函数我都将C语言中的注释迁移过来了,而且我从使用角度对函数的api进行了微调!!!(还不快快谢谢小玺玺→_→)
在这里插入图片描述
我已经在项目主页的README中补充了包中所有的函数/变量的层级关系及接口声明。这样如果我们知道要调用的函数名,可以直接在项目主页中搜索这个函数名,得到调用方式。比如softPwmCreate这个函数的调用方式就是from WiringPi.softdriven import softPwmCreate
在这里插入图片描述

三 开发过程

这里我聊聊聊聊自己的开发细节,先说说为啥自己心血来潮要封装WiringPi,首先是因为去年Arui在利用X3的PWM接口时,官方提供的python版本的控制PWM出现抖动的问题,C++版本的wiringPi能满足要求,但没法python调用。当时快速给他用Cython包装了他要的接口,已经验证通过了。然而最近另一位开发者要使用这个东西,但是在他的板子上怎么也运行不起来,我又没太多时间教他怎么配置这个,为了减少各位在这种造轮子上花费的时间,所以我要将WiringPi这个库彻底封装。

该项目从1月10日创建,到目前出了一版,用了1个月的时间,在构造这个项目的时候,我就一直在思考构造一个“好用”的Package都要考虑什么,目前我想到的点主要有以下这些:

  • 接口设计。Python的习惯是利用返回值返回数据,而C语言是通过传递指针来输出数据的。我需要理解每个函数的用法,并制定相关的优化方式。
  • 安装简化。用最少的指令完成项目的编译与安装。即,利用pip install安装包,利用python setup.py生成包。
  • 注释完善/辅助开发。利用好vscode开发的自动弹出功能,展示函数的接口以及相关的注释,让内容变得透明。
  • 撰写好用的开发文档。从博客/项目readme等角度,减少用户的学习成本。

除了“接口设计”这一部分是开发部分的工作,其他的工作都是围绕着生态展开的,由此也可见生态是多么重要。封装WiringPi这个是个大工程,下面列举出我在开发时为了提升使用体验做出的努力😎:

  • 检查了所有函数的接口,并对其中一些函数的使用方式进行了优化。比如

    • 对于通过输入参数类型为指针来返回值的,通过lambda表达式进行了新的定义。函数void wiringPiVersion(int *major, int *minor)返回的版本信息,存储在major, minor中,这样我就可以将其封装为封装在返回值中,在py中可以通过major, minor = wiringPiVersion()的方式进行调用。
    • 优化了一些实际返回值是int但实际上应该是bool的函数。C语言中用1,0表示true,false,防止py使用时产生疑惑,我从其实现代码中将只返回0,1的函数返回类型改为bool。
    • 输入参数包含数组的函数,适配为输入np.ndarray的形式。比如函数void ds1302clockWrite(const int clockData[8]);需要输入一个包含8个元素的数组,对应的python声明为def ds1302clockWrite(clockData: numpy.ndarray[numpy.int32]) -> None,代码中会自动校验元素个数。
    • 按照传感器的类型进行了分类与整合。比如GPIO扩展芯片mcp23s08, pcf8574,我把相关的函数封装在WiringPi.gpio模块里。
  • 简化安装过程,编译这个包只需要python3 setup.py bdist_wheel即可

    • 在setup.py过程中就已经完成了辅助开发的构造。封装c++生成的so文件,vscode是无法弹出其中的函数的,也就意味着so文件对用户来说是不透明的。所以必须基于so文件生成对应的.pyi声明文件。
      • 最开始使用的是pybind11-stubgen,但是问题较多,C++17的特性支持的一般,研究测试了一段时间后放弃。
      • 目前使用的是mypy来导出大部分函数的声明与注释。但是奇怪的是每个模块的doc无法导出,只能在setup.py中补充个后处理函数来解决这个问题。
    • 在setup.py中利用cmakelists.txt对模块进行编译。就是将正常编译cmake项目关联的指令整理在一起,完成自动编译。当然由于包含模块的后处理之类的,这里对其中的一些关键函数进行了重载。
  • 整理了所有函数的注释。WiringPi中很多注释是写在.c文件里了,我把这些注释都封装在pybind中,量真的很大😭。

开发中我经常能遇到undefined symbol的问题,这里记录下导致这个问题的几种情况。
在这里插入图片描述

  • 头文件忘记extern "C"。比如报错说是_Z10rht03Setupii是个未定义的符号,
    • 首先利用c++filt _Z10rht03Setupii解析出函数声明:rht03Setup(int, int)
    • 然后nm -g /usr/local/lib/libwiringPi.so列举出这个库是否包含rht03Setup
    • 发现库包含这个函数,所以看头文件,发现没写extern "C"。这会导致C++项目链接到这个库时,无法引用相关的函数。补充上即可。
      在这里插入图片描述
  • Makefile漏掉了某些.c文件,比如softServo这个就没编译。同样,我利用nm工具发现库中就没这个函数,就直接去检查是否编译了。修复这个问题就能正常使用了。

四 小结

这一个月,下班回家后就开始研究封装相关的技术和工具,几乎天天从11点整理到2点,其实如果只是封装的话并不难,主要是很多传感器我要分类,我要研究用法。而且经常凌晨拉着晟哥哥讨论怎么设计结构,获取使用体验等等(真的感谢)。真心希望各位后续不会在接口的使用上困住。

WiringPi这个项目还有很多工作要做,在未来的工作中还需要继续完善与优化,还请各位多多关注仓库主页:Pybind11-WiringPi。后续的工作主要还是围绕以下几点:

  • 增加BPU推理python自定义层的支持。目前自定义层仅用于c++推理,导致部分模型,比如HED边缘检测算法,部署难度大幅增加。
  • 增加树莓派引脚的适配。我目前使用的WiringPi是地平线X3开发板专用的,为了避免对树莓派用户开发干扰,会补充个全局变量来解决。这部分工作其实就是解决设备兼容问题,欢迎树莓派用户一起来搞。
  • 尽可能补充各个模块函数的使用demo。降低用户的学习/开发成本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1442355.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenAI给DALL-E 3来了个新动作,加入了全新水印技术

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

老胡的周刊(第128期)

老胡的信息周刊[1]&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 &#x1f3af; 项目 coze-discord-proxy[2] 代理 Discord-Bot 对…

018 Linux

文章目录 操作系统定义分类Linux系统构成 Linux文件系统Linux常用命令基础操作命令文件操作压缩解压权限管理显示展示命令其他命令 vi编译器操作使用 添加用户基本概念用户管理命令 ubuntu软件安装ssh服务终端启动Python服务 操作系统 定义 操作系统是管理计算机硬件与软件资…

【超高效!保护隐私的新方法】针对图像到图像(l2l)生成模型遗忘学习:超高效且不需要重新训练就能从生成模型中移除特定数据

针对图像到图像生成模型遗忘学习&#xff1a;超高效且不需要重新训练就能从生成模型中移除特定数据 提出背景如何在不重训练模型的情况下从I2I生成模型中移除特定数据&#xff1f; 超高效的机器遗忘方法子问题1: 如何在图像到图像&#xff08;I2I&#xff09;生成模型中进行高效…

archlinux 使用 electron-ssr 代理 socks5

提前下载好 pacman 包 https://github.com/shadowsocksrr/electron-ssr/releases/download/v0.2.7/electron-ssr-0.2.7.pacman 首先要有 yay 和 aur 源&#xff0c;这个可以参考我之前的博客 虚拟机内使用 archinstall 安装 arch linux 2024.01.01 安装依赖 yay 安装的&#…

堆排序----C语言数据结构

目录 引言 堆排序的实现**堆的向下调整算法** 对排序的时间复杂度建堆的时间复杂度&#xff1a;排序过程的时间复杂度&#xff1a;总体时间复杂度&#xff1a; 引言 堆排序&#xff08;Heap Sort&#xff09;是一种基于比较的排序算法&#xff0c;利用堆的数据结构来实现。它的…

数据湖的整体思路

湖本质上是一个集中化&#xff0c;中心化的&#xff0c;一体化的存储技术&#xff0c;并且在其之上追求技术架构的统一化&#xff0c;如流批一体&#xff0c;服务分析一体化。 当数据湖成为中心&#xff0c;那么就可以围湖而建“数据服务环”&#xff0c;环上的服务包括了数仓、…

基于tomcat运行jenkins常见的报错处理

目录 1.jenkins.util.SystemProperties$Listener错误 升级jdk11可能遇到的坑 2.java.lang.RuntimeException: Fontconfig head is null, check your fonts or fonts configuration 3.There were errors checking the update sites: UnknownHostException:updates.jenkins.i…

JAVA Web 学习(五)Nginx、RPC、JWT

十二、反向代理服务器——Nginx 支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&#xff0c;即使运行几个月也不需要重新启动&#xff0c;还能在不间断服务的情况下对软件版本进行热更新。性能是 Nginx 最重要的考量&#xff0c;其占用内存少、并发能力强、能支持…

初识Solidworks:我的第一份作业的感想

从来没用CAD软件画过机械设计图。但我脑子里有一种概念&#xff0c;无非就是把尺规作图软件化&#xff0c;更方便画图、更方便修改、更方便打印一些。但第一份 Solidworks 作业就颠覆了我的认知&#xff0c;考虑到这个软件的上市时间&#xff0c;让我意识到自己对 CAD 软件的认…

【大厂AI课学习笔记】【1.5 AI技术领域】(8)文本分类

8,9,10&#xff0c;将分别讨论自然语言处理领域的3个重要场景。 自然语言处理&#xff0c;Natual Language Processing&#xff0c;NLP&#xff0c;包括自然语言识别和自然语言生成。 用途是从非结构化的文本数据中&#xff0c;发掘洞见&#xff0c;并访问这些信息&#xff0…

C++——二叉树

引入 map和set特性需要先铺垫二叉搜索树&#xff0c;而二叉搜索树也是一种树形结构 二叉搜索树的特性了解&#xff0c;有助于更好的理解map和set的特性 1.二叉搜索树的概念及优缺点 1.1二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或…

CSP-202109-1-数组推导

CSP-202109-1-数组推导 解题思路 如果 currentValue 与 previousValue 相同&#xff0c;说明这个值不是一个独特的新值&#xff0c;因此只将它加到 sumTotal 上。如果 currentValue 与 previousValue 不相同&#xff0c;说明这是一个新的独特值&#xff0c;因此既将它加到 su…

逐行拆解Guava限流器RateLimiter

逐行拆解Guava限流器RateLimiter 常见限流算法 计数器法 设置一个时间窗口内允许的最大请求量&#xff0c;如果当前窗口请求数超过这个设定数量&#xff0c;则拒绝该窗口内之后的请求。 关键词&#xff1a;时间窗口&#xff0c;计数器。 举个例子&#xff0c;我们设置1秒钟…

面试经典150题 -- 栈(总结)

总的链接 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台 关于栈 -- stack 的学习链接 c的STL中的栈 -- stack-CSDN博客 20 . 有效的括号 这题直接用栈模拟就好了; 这里用一种取巧的方法 , 当遇见左括号&#xff0c;加入右…

【Langchain+Streamlit】旅游聊天机器人

【LangchainStreamlit】打造一个旅游问答AI-CSDN博客 项目线上地址&#xff0c;无需openai秘钥可直接体验&#xff1a;http://101.33.225.241:8502/ github地址&#xff1a;GitHub - jerry1900/langchain_chatbot: langchainstreamlit打造的一个有memory的旅游聊天机器人&…

Linux 命令基础

Shell概述 Linux操作系统的Shell作为操作系统的外壳&#xff0c;为用户提供使用操作系统的接口。它是命令语言、命令解释程序及程序设计语言的统称。 Shell是用户和Linux内核之间的接口程序&#xff0c;如果把硬件想象成一个球体的中心&#xff0c;内核围绕在硬件的外层管理着…

【JS逆向九】逆向某混淆网站源码,模拟 加密,解密,密钥生成

逆向日期&#xff1a;2024.02.09 使用工具&#xff1a;Node.js 是否有混淆&#xff1a;源代码混淆 加密方法&#xff1a;AES标准库 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 可使用AES进行解密处理&#xff08;直接解密即可&#xff0…

读千脑智能笔记09_大脑的错误信念

1. 人类智能的未来 1.1. 气候变化如此剧烈&#xff0c;在下一个百年里&#xff0c;一些城市很可能会不再适合人类居住&#xff0c;大面积的农业区或将变得更加贫瘠 1.1.1. 气候并非唯一需要关注的问题 1.1.2. 人类的一些技术&#xff0c;如核武器和基因编辑&#xff0c;为少…

win32编程系统BUG(Win32 API中的WM_SETTEXT消息)

由于频繁使用Win32 API中的WM_SETTEXT消息&#xff0c;导致内存占用直线上升。 暂未找到有效解决方案。