Python学习之路(5)— 使用C扩展
Python学习之路(5)— 使用C扩展
一、前言
参考:https://www.cnblogs.com/yinguo/p/4641349.html
Python C扩展是指用C语言编写的代码,然后编译成Python可以调用的库。这样可以提高Python代码的执行效率,或者实现某些Python无法直接实现的功能。
开发平台: Ubuntu 20.04.6 LTS
二、引入 Python.h 头文件
首先编写c扩展需要引入Python.h头文件,以ubuntu20为例,该文件在如下路径:
/usr/include/python3.8/
如果没有,可以使用如下目录安装
sudo apt-get install python3-dev
我们后面在编译共享库的时候需要指定该路径
三、编写处理函数
新建 hello.c文件,我们需要按照指定的格式编写函数,才可以让python调用;
函数一般声明成 static ,第一个参数是一个默认传入的 Python 对象,第二个参数是我们调用时传入的参数
static PyObject * hello_sum(PyObject *self, PyObject *args)
函数接受的参数是从 Python 环境下传入的,这和 C 中看到的函数是不同的,在 Python 的世界中,一切都是对象。所以,包装函数中首先要处理的问题就是解析从 Python 占获取的参数(实际上它是一个序列化后的字符串);
我们常用的处理参数的函数是: PyArg_ParseTuple
例如我们这里要解析两个整数,我们先定义两个整数,如何使用PyArg_ParseTuple解析获取:
int a;
int b;
PyArg_ParseTuple(args, "i|i", &a, &a);
其中i|i 就表示要把传入的参数args解析成两个整数, 怎样我们就获得了想要传入的两个整数a和b;
同样的,我们要把值返回到 Python 环境中,也需要经过一些处理才行,常用的函数是Py_BuildValue,这个函数的用法和上一步中的 PyArg_ParseTuple 是一样的,但它们过程相反,Py_BuildValue 把 C 中的值按给定的格式格式化成 Python 需要的对象。
return Py_BuildValue("i", (a+b));
编写完整的hello_sum函数如下所示:
static PyObject * hello_sum(PyObject *self, PyObject *args) {int a, b, sum;if (!PyArg_ParseTuple(args, "ii", &a, &b))return NULL;sum = a + b;return Py_BuildValue("i", sum);
}
四、定义模块
我们把上面的函数实现完成之后,我们需要定义一个模块并将其导出。
首先,我们要在一个类型为 PyMethodDef 的结构体中注册我们需要导出到 Python 中的函数:
static PyMethodDef ExtendMethods[] = {{"sum", hello_sum, METH_VARARGS, "Compute sum of two integers."},{NULL, NULL, 0, NULL}
};
这个PyMethodDef 结构体有四个成员:
- “sum”: 导出后在 Pyhton 中可见的方法名;
- hello_sum: 在C中实际调用的函数;
- METH_VARARGS: 表示传入方法的是普通参数,当然还可以处理关键词参数;
- 第四个是这个方法的注释。
然后我们构建一个PyModuleDef 类型的结构体,就是我们要定义的模块了
static struct PyModuleDef hellomodule = {PyModuleDef_HEAD_INIT,"hello", // 模块名"A simple example of Python C extension", // 模块文档-1, // 模块状态ExtendMethods// 模块的方法列表
};
这个PyModuleDef 结构体的成员如下:
PyModuleDef_HEAD_INIT:初始化头部信息,确保结构体的正确初始化,使其符合 Python C API 的要求;hello:这个模块的名称,我们在python中使用的就是这个模块名称;- 第三个成员指明这个模块的文档,可以是
NULL; - 第四个成员表示模块的每个解释器状态的大小,如果模块将状态保存在全局变量中,则为-1;
- 第五个成员就是我们刚才定义的这个模块的方法列表;
五、初始化模块
使用如下方式初始化模块,编写模块初始化函数如下所示,PyMODINIT_FUNC 被用来声明模块初始化函数的返回类型。模块初始化函数会被 Python 调用,用于注册扩展模块及其功能。模块初始化函数的名称通常是 PyInit_<module_name>,其中 <module_name> 是扩展模块的名字。
PyMODINIT_FUNC PyInit_hello(void) {return PyModule_Create(&hellomodule);
}
六、编译共享库
使用如下命令编译共享库
gcc -shared -o hello.so -fPIC hello.c -I/usr/include/python3.8
编译完成后我们可以在当前目录下看到名为hello.so的共享库
七、 python运行
编写python代码如下所示:
import hello
print(hello.sum(4, 3))
运行结果如下所示

八、使用setup.py
上面我们通过gcc创建共享库的方式成功实现了C扩展,但是需要在共享库存在的目录下才可以调用使用;
Python提供了一个将C扩展安装到Python的site-packages目录下的方法,这样使得我们可以在任意目录的Python脚本中导入并使用这个C扩展模块。
编写setup.py如下所示:
from setuptools import setup, Extension# 定义C扩展模块
module = Extension('hello', sources=['hello.c'])# 设置和安装
setup(name='HelloPackage',version='1.0',description='A simple hello package',ext_modules=[module]
)
创建命令如下所示,使用 --user 选项会将包安装到用户目录中的 site-packages 目录,而不需要管理员权限。
python3 setup.py install --user
相关文章:
Python学习之路(5)— 使用C扩展
Python学习之路(5)— 使用C扩展 一、前言 参考:https://www.cnblogs.com/yinguo/p/4641349.html Python C扩展是指用C语言编写的代码,然后编译成Python可以调用的库。这样可以提高Python代码的执行效率,或者实现某些…...
动态规划34:446. 等差数列划分 II - 子序列
动态规划解题步骤: 1.确定状态表示:dp[i]是什么 2.确定状态转移方程:dp[i]等于什么 3.初始化:确保状态转移方程不越界 4.确定填表顺序:根据状态转移方程即可确定填表顺序 5.确定返回值 题目链接:446.…...
PPT画图——如何设置导致图片为600dpi
winr,输入regedit打开注册表 按路径找,HKEY_CURRENT_USER\Software\Microsoft\Office\XX.0\PowerPoint\Options(xx为版本号,16.0 or 15.0或则其他)。名称命名:ExportBitmapResolution 保存即可,…...
【模块系列】STM321.69TFT屏幕
前言 在翻翻自己的器件盒的时候,发现这块好久之前买的TFT屏了,想起还没有用STM32点亮过,手头上正好有立创的梁山派STM32F4,就试着按照网上的文章教程顺便移植个LVGL看看,然后就有了就本文。 代码工程命名的是LvglDemo&…...
大模型辅助测试的正确打开方式?
测试的基本目的之一,是对被测对象进行质量评估。换言之,是要提供关于被测对象质量的“确定性”。因此,我们很忌讳在测试设计中引入“不确定性”,比如采用不可靠的测试工具、自动化测试代码逻辑复杂易错、测试选择假设过于主观等等…...
三相电的相电压、线电压、额定值、有效值,变比,零序电压,零序电流,三相三线制的三角形连接,三相四线制的星形连接
在二次设备配置中经常有根电压系统相关的名词,本身不是学电气的,有些名词经常查了忘,后续工作所有遇到跟电气相关的知识总结在此帖,便于后续直接查看,避免每次都要重新查、重新梳理。 相电压和线电压的关系是根号3倍&a…...
电商网站的基础用户数在100万,日活跃用户数在1万左右,系统下单TPS最大支持1000,应用服务要保证高可用。请预估该网站每天的使用成本。
要预估一个电商网站每天的使用成本,我们需要考虑多个因素,包括计算资源、数据库、缓存、存储、网络流量、负载均衡、安全服务、监控与日志等。以下是基于您提供的信息(基础用户数100万,日活跃用户数1万,系统下单TPS最大…...
线性代数期末总复习的点点滴滴(1)
一、可逆矩阵、行列式、秩的关系 1.行列式与可逆矩阵的关系 所以,不难看出矩阵可逆的充分必要条件是该矩阵的行列式不为0。 2.接着来看,满秩和矩阵行列式的关系 不难看出满秩和行列式不为0是等价的。 3.再来看,满秩和矩阵可逆的关系 说明了…...
python+reportlab创建PDF文件
目录 字体导入 画布写入 创建画布对象 写入文本内容 写入图片内容 新增页 画线 表格 保存 模板写入 创建模板对象 段落及样式 表格及样式 画框 图片 页眉页脚 添加图形 构建pdf文件 reportlab库支持创建包含文本、图像、图形和表格的复杂PDF文档。 安装&…...
2024最新qrcode.min.js生成二维码Demo
找了一堆代码一堆GPT,终于给写对了: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…...
【Microi吾码】开源力量赋能低代码创新,重塑软件开发生态格局
我的个人主页 文章专栏:Microi吾码 一、引言 在当今数字化浪潮汹涌澎湃的时代,软件开发的需求呈现出爆发式增长。企业为了在激烈的市场竞争中脱颖而出,不断寻求创新的解决方案以加速数字化转型。传统的软件开发方式往往面临着开发周期长、技…...
Github - 如何提交一个带有“verified”标识的commit
Github - 如何提交一个带有“verified”标识的commit 前言(Why) 今天在Github上浏览某项目的commit记录的时候发现,有的commit记录带有verified绿色标识,有的带有橘色的Unverified标识,还有的什么都不显示。 既然我是根正苗红的作者(bushi)…...
HCIA笔记9--NAT、ACL与链路聚合
1. ACL ACL: 访问控制列表, Access Control List。 通过定义规则来允许或拒绝流量的通过。 1.1 ACL分类 1.2 配置实例 如图所示,对R2的访问只允许192.168.1.0/24网段。 我们可以配置基本acl来限制 acl 2000 acl number 2000 rule 5 permit source 192.168.1.0 0…...
SCSA:探索空间与通道注意力之间的协同效应
文章目录 摘要1 引言2 相关工作2.1 多语义空间信息2.2 注意力分解 3 方法3.1 共享多语义空间注意力:空间与通道分解3.2 渐进式通道自注意力3.3 协同效应3.4 注意力机制的整合 4 实验4.1 实验设置4.2 图像分类4.3 目标检测4.4 分割4.5 消融研究 5 可视化与分析5.1 注…...
深度学习助力股市预测:LSTM、RNN和CNN模型实战解析
作者:老余捞鱼 原创不易,转载请标明出处及原作者。 写在前面的话:众所周知,传统的股票预测模型有着各种各样的局限性。但在我的最新研究中,探索了一些方法来高效预测股市走势,即CNN、RNN和LSTM这些深度学习…...
组件库TDesign的表格<t-table>的使用,行列合并以及嵌入插槽实现图标展示,附踩坑
碎碎念:有点难用,不丝滑(以下介绍的难点不是真的难,只是有点点点难用) 背景:需要实现表格的行列合并以及图标的嵌入,想到使用组件库组件来方便开发 链接:TDesign Web Vue Next 难点…...
jwt在express中token的加密解密实现方法
在我们前面学习了 JWT认证机制在Node.js中的详细阐述 之后,今天来详细学习一下token是如何生成的,secret密钥的加密解密过程是怎么样的。 安装依赖 express:用于创建服务器jsonwebtoken:用于生成和验证JWTbody-parser࿱…...
结构体、共用体的字节对齐
结构体 结构体嵌套时:先算一下嵌套的结构体大小 嵌套进来的结构体大小为16字节,仍然进行,8字节对齐 typedef struct {char name[20];//20字节//000开始 20字节 019 struct{int day; //000开始 4字节 003char swx; //004开始 1…...
【YOLOv3】源码(train.py)
概述 主要模块分析 参数解析与初始化 功能:解析命令行参数,设置训练配置项目经理制定详细的施工计划和资源分配日志记录与监控 功能:初始化日志记录器,配置监控系统项目经理使用监控和记录工具,实时跟踪施工进度和质量…...
帧缓存的分配
帧缓存实际上就是一块内存。在 Android 系统中分配与回收帧缓存,使用的是一个叫 ION 的内核模块,App 使用 ioctl 系统调用后,会在内核内存中分配一块符合要求的内存,用户态会拿到一个 fd(有的地方也称之为 handle&…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
