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&…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
OCR MLLM Evaluation
为什么需要评测体系?——背景与矛盾 能干的事: 看清楚发票、身份证上的字(准确率>90%),速度飞快(眨眼间完成)。干不了的事: 碰到复杂表格(合并单元…...
